代码托管地址:https://git.oschina.net/wl/AirMVC
名称含义:
airmvc喻意像空气一样轻的框架。这里的mvc并不是指传统的mvc,这里没有model,m表示的是ModulesManager。但有传统mvc中逻辑视图代码分离的Controller和View。
框架用途:
主要目的在于降低代码耦合和减少主程序体积。
airmvc引导使用者运用RSL技术和类似flex
modules的模块分离思想去设计你的程序,达到降低模块之间的耦合度和减少主程序的体积的目的,有助于团队合作,便于维护和减少程序初始化的时间。RSL技术可以使公用类不编译到程序里,减少每个模块的体积,而且在IDE中也跟普通类一样有API智能提示,不影响开发。
使用方法:
Airmvc提供两种模式,加载模式和非加载模式。加载模式是将各模块分别编译成swf,在运行时加载,因为使用了RSL以及各模块在设计时互不依赖,所以打包的swf文件可以达到最小化;非加载模式则是把所有的模块都编译进主程序,方便调试,如果程序不是很大的话发布时也可以使用非加载模式。
具体步骤如下:
1、建一个库文件,把mornUI和airmvc添加进去,并在这里添加项目的公共类,编译成swc作为RSL。
2、新建工程,在工程里编写模块。每个模块里都应该至少包括一个Controller的子类,和一个View的子类。Controller子类之间可以相互接发消息,宏观表现为模块间通讯。Controller子类需要注册一个View子类,CV之间可以相互接发消息,即为模块内通讯。因为每个模块之间都是通过消息通讯,互不依赖,所以可以单独编译成swf而不受其他模块影响。模块内通讯是为了将逻辑代码与视图代码分离,降低耦合度。
View子类本身是一个flash里的容器,可以随意添加子显示对象。它的子显示对象我们在这里称为ViewComponent。ViewComponent可以通过Dispatcher.send(msg:String,
source:DisplayObject, ...
args)方法来发送模块内部消息,但不能接收任何消息。source参数传ViewComponent(即this)本身即可,Dispatcher.send方法内会从其祖先容器中找到View的子类,并使用其向Controller子类发送消息的功能。
View子类的文件需要包含mxmlc的编译参数,使用FlashDevelop的快速编译功能打包模块。因为swf的入口文件必须是可显示类型,所以使用view作为编译入口而不是使用controller。为了保证controller能编译到swf里面,view中需要引用controller。推荐的作法是在view里使用controller的静态常量作为消息名。
运作流程:
airmvc使用ModulesManager.init(config:*,
isLoadMode:Boolean =
true)方法来初始化。config可以是XML或ModulesConfig类,里面记录了模块的相关信息。这里简单介绍一下使用加载模式的运作流程。
初始化的时候airmvc会记录所有模块的类定义和加载路径,然后监听以类定义作为消息名的消息事件。最后启动在config里配置的第一个模块,下一个模块则通过第一个模块发送消息来启动。
例如消息名为”begin.BeginC”,ModulesManager收到这个消息后会从服务器加载对应的模块到当前域,然后获取begin.BeginC定义,实例一个BeginC并保持对它的引用,再去掉对这个消息的监听,转由BeginC监听。以后其他模块再次发送”begin.BeginC”这个消息的时候,由BeginC的startup(args:Array)方法来处理。我们可以在startup方法里进行初始化并注册View的子类,打开或关闭窗口等的工作。
因为ModulesManager收到任何消息时都是执行加载模块的方法,但此时它并不知道应该加载哪个模块,所以第一次启动模块的消息应该带有一个与模块定义一样的参数,例如,broadcast(“begin.BeginC”,”begin.BeginC”);
因为airmvc使用了morn的资源加载管理器,所以必须先初始化morn框架再初始化airmvc。
具体内容请参考demo。
Demo说明:
编译core项目的时候需要引入airmvc和morn。
如果你想直接运行demo看效果可以直接运行bin下的Game.swf或Game-debug.swf。
Game.swf只有2KB,运行时加载assets/library.swf和assets/modules/里的模块。
Game-debug.swf把需要用到的库和所有模块都编译到同一个文件并且包含调试信息,因此比较大。
虽然在这个demo里加载模式的所有文件总和比非加载模式的要大,但当你的工程达到一定程度,编译文件超过1M时,加载模式带来的好处是显而易见的。
作者附言:
本人单身屌丝程序员一枚,喜欢独来独往,因此以下自称为寡人。airmvc只是寡人觉得自己在公司所用的框架比较臃肿,耦合度太高,不易维护,为了弱化(还不敢说能解决)这些问题而设计的。airmvc仅仅是寡人在了解了RSL技术和模块分离思想后设计出来的,没经历过任何项目的考验,如果在框架中埋了什么大坑请吐槽。寡人比较倾向简洁高效的东西,如果你有什么好的方法去实现请留言。
airmvc可以说是专门针对游戏开发而生的吧,寡人自大四开始就一直跟flash游戏打交道,至此也快两年了。受职业局限只能从接触过的游戏框架去思考问题。现在在公司里用的框架是不考虑model发送消息来通知view去更新的,而是直接在Controller里接收Socket模块发过来的消息然后由Controller更新视图。寡人也觉得这样比较简便,所以在airmvc里没有使用像puremvc那样可以发送消息的Proxy类作为远程代理。在airmvc里的model类结构跟项目有关,应该自行定义,一般是单纯的值对象类(VO)就足够了,或者建一个DataManager类来管理数据。
说到这里顺便提一下puremvc框架。本来寡人是想使用RSL和模块分离思想结合puremvc实现一套工作流的。在看完puremvc所有的源码后,再一次让寡人想到了“编程不仅是一门技术,更是一门艺术”这句话。puremvc巧妙地将6个设计模式(寡人能数出来的是6个)组合到一起来实现mvc设计思想。不过寡人觉得有一点不足的是解耦过度了,Command文件过多,维护起来相当麻烦(可能是寡人资历尚浅而且又没深入使用过puremvc的原因),江湖中也传言puremvc普遍存在滥用的情况,初学者会越用越乱,所以寡人干脆就把以前用于规范项目结构的airmvc1.0升级到了airmvc2.0。现在比1.0多了一个类(实际是两个,还有一个包外类),但功能却有了很大变化。使用面向对象语言实现的框架本来应该考虑开放-封闭原则的,应该依赖接口而不是具体类,但想来想去都不知道怎样使用接口,所以还望有高人能指点一二。