Eric-PMVC-Framework-001
基于mvc设计思想、结合CocosCreator。
目标1:尽可能的降低model、view、ctrl之间的耦合
目标2:尽可能的复用model和view
目标3:尽可能的使框架结构清晰,增删查改较方便快捷
目标4:尽可能的减少代码创建视图结构复杂度
目标5:尽可能的少创建新的数据
目标6:尽可能的方便响应、控制、更新
目标7:尽可能的多开发通用一套框架
目标8:尽可能的方便扩展
目标8:暂时想到这么多
MVC
- Model:数据
- View:视图组件
- Controller:控制逻辑
将数据,视图组件和控制逻辑进行分离。但Ctrl保持了M、V的引用,或者说只是M、V的解耦。
PMVC
在传统MVC基础上做了许多的改进,通过结合多个“设计模式”的应用,让耦合性变得更低。

如上图,PMV结构中Model,View,Controller之间并没有任何的直接通信。
在PureMVC中,Model,View,Controller是三个单例模式类,三者合称为核心层或核心角色,换句话说就是Manager管理类,他们分别定义了字典用于保存引用,以及Register,Add,Remove,Retrieve等方法,将使用到的具体层(Model,View,Controller),保存到字典中进行统一管理,这样,在我需要获取某一个具体层时,我可以通过key直接访问到它们,虽然保留了存储,但通常不去直接获取另一个管理的对象(尽可能的解耦)。
这里通过一个上层的接口来负责所有核心层(Model,View,Controller)的管理和操作(外观设计模式)。
单例模式:一个单一的类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
外观模式:为一组子系统或是接口提供一个统一的界面,以简化其复杂度,降低耦合性
Facade(单例)提供了与核心层通信的唯一接口,以简化开发复杂度。
这样上面的Controller中,获取View和Model,或者View中,获取Model,均统一使用Facade进行管理。对于使用者来说,只需要知道Facade类存在就可以了。降低了MVC三层之间的耦合性。
Facade类应被当成抽象类, 永远不被直接实例化,你应该具体编写 Facade 的子类,添加或重写 Facade 的方法来实现具体的应用。这个类命名为“ApplicationFacade”(命名随意)。
Facade 类会在构造方法包含对核心 MVC 三者单例的构造。
Model 与 Proxy

Model即上图中的数据(Data Object),游戏是基于数据驱动的,比如角色的数据,包括HP,MP,金币,等级,经验,技能等等,Data Object即是以任意结构存储数据的对象。
在PureMVC中,不直接操作model数据,对Model的增删改查均是通过Proxy来进行管理(代理设计模式)。
代理模式:为其它对象提供代理以控制该对象的访问,即代理人,在PureMVC中被用来控制和管理数据模型
Model 保存对 Proxy 对象的引用,Proxy 负责操作数据模型,与远程服务通
信存取数据。这样保证了Model 层的可移植性。
Model只和Facade通信,尽可能的降低和别的对象耦合。
需要注意的是,并不是一个Model对应一个Proxy,如果是这样就太繁琐了,比如一个模块中,可能包括很多种不同的Model数据,可以定义多个不同的Model,但可以通过一个Proxy进行管理,这样更方便。
View 与 Mediator
和model层类似,View是通过中介Mediator来操作具体的视图组件(View Component)。包括:添加事件监听器 ,发送或接收 Notification ,直接改变视图组件的状态。

View 保存对 Mediator 对象的引用 。这样做实现了把视图和控制它的逻辑分离开来。对于View中组件的定义和初始化都在Mediator中定义和实现,这样即使UI重建,也只是更改Mediator。
Proxy更侧重于控制数据的访问,相当于真实数据的代表,而Mediator则更侧重于数据的交互(封装了一系列对象的交互)
通常会以同步的方式取得或设置Model数据。Proxy 可能会提供访问 DataObject 部分属性或方法的 API,也可能直接提供 Data Object 的引用(但不建议这样做,我们应该保护Model,提供相应的接口来访问)。如果提供了更新 Data Object 的方法,那么在数据被修改时可能会发送一个 Notifidation 通知系统的其它部分。
这里Notification通知,其实就是观察者模式,当一个对象发生改变的时候,同时也需要有很多其它的对象要对此做出响应,这时候就要使用观察者模式了,发布-订阅的模式,比如我们订阅了某个微信公众号,公众号发表了一篇文章,所有订阅的用户都可以收到提醒,这在游戏中无处不在,当Model发生变化的时候,通知View组件进行更新。那么在View中,就会有相应的方法来处理Notification通知,并进行相应的逻辑处理。
Proxy只发送Notification通知(在数据改变的时候),他并不处理Notification通知,他并不关心View组件如何变化。
Proxy 对象不应该通过引用、操作 Mediator 对象来通知系统它的 DataObject(数据对象)发生了改变。
也就是说,Mediator可以获取Proxy,但Proxy中不应该获取Mediator,如果要通知View层进行更新,发送Notification通知即可。
(Proxy 不关心这些 Notification 被发出后会影响到系统的什么)
这样Proxy和Mediator之间只存在单向耦合。
Controller 与 Command
Controller保存了所有Command的映射,Command 类是无状态的,只在需要时才被创建。(命令设计模式)
Command 可以获取 Proxy 对象并与之交互,发送 Notification,执行其他
的 Command。经常用于复杂的或系统范围的操作,如应用程序的“启动”和
“关闭”。应用程序的业务逻辑应该在这里实现。
Facade 需要在启动时初始化 Controller,建立 Notification 与 Command的映射。
Controller 会注册侦听每一个 Notification,当被通知到时,Controller 会实例化一个该 Notification 对应的 Command 类的对象。最后,将 Notification 作为参数传递给execute 方法。
也就是说,Command的执行是通过发送Notification通知操作的。
Command 对象是无状态的;只有在需要的时候( Controller 收到相应的Notification)才会被创建,并且在被执行(调用 execute 方法)之后就会被删除。所以不要在那些生命周期长的对象(long-living object)里引用 Command 对象。
在运行中,可以通过Command来初始化Proxy和Mediator,即注册到Facade中。
Façade 与 Core
Façade 类应用单例模式,它负责初始化核心层(Model ,View 和
Controller),并能访问它们的Public 方法。
Façade 类应被当成抽象类, 永远不被直接实例化。
这样,在实际的应用中,你只需继承 Façade 类创建一个具体的 Façade 类就
可以实现整个 MVC 模式,并不需要在代码中导入编写 Model,View 和
Controller 类。
Proxy、Mediator 和 Command 就可以通过创建的 Façade 类来相互访问通
信。
Observer 与 Notification
Facade 保存了Command 与Notification 之间的映射。当Notification(通知)被发出时,对应的 Command(命令)就会自动地由 Controller 执行。Command 实现复杂的交互,降低View 和Model 之间的耦合性。
Mediator发送、声明、接收Notification
当用 View 注册 Mediator 时,Mediator 的 listNotifications 方法会被调用,
以数组形式返回该Mediator 对象所关心的所有Notification。
之后,当系统其它角色发出同名的 Notification(通知)时,关心这个通知的
Mediator 都会调用 handleNotification 方法并将 Notification 以参数传递到
方法
在很多场合下 Proxy 需要发送 Notification(通知),比如:Proxy 从远程服
务接收到数据时,发送 Notification 告诉系统;或当 Proxy 的数据被更新时,
发送Notification 告诉系统。
如果让 Proxy 也侦听 Notification(通知)会导致它和 View(视图)层、
Controller(控制)层的耦合度太高。
View 和 Controller 必须监听 Proxy 发送的 Notification,因为它们的职责是
通过可视化的界面使用户能与Proxy 持有的数据交互。
不过对View 层和Controller 层的改变不应该影响到Model 层。
浙公网安备 33010602011771号