pureMVC
pureMVC 架构图
一个概略图
观察者模式
请看我的上一篇博客 传送门
Notification
Notification 类 是PureMVC(js)的消息类
结构如下
function Notification(name, body, type)
{
this.name = name; // 消息名
this.body = body; // 消息实体内容
this.type = type; // 消息类型
};
Observer
observer: 观察者
Observer.prototype.notify = null; // Observer对象(观察者)接收到消息之后执行的回调函数
Observer.prototype.context = null; // context是回调函数的执行作用域
Observer.prototype.notifyObserver = function (notification)
{
// 在context(回调函数执行作用域)中调用notify方法(回调函数)。
this.getNotifyMethod().call(this.getNotifyContext(), notification);
};
Notifier
Notifier: 通知者
Notifier类是MacroCommand类、SimpleCommand类、Mediator类和Proxy类的基类,它通过sendNotification()方法用来发送消息。
Notifier.prototype.sendNotification = function(notificationName, body, type)
{
var facade = this.getFacade();
if (facade)
{
facade.sendNotification(notificationName, body, type);
}
};
Notifier.prototype.getFacade = function()
{
// multitonkey是全局Facade的唯一键值,通过这个key值我们可以索引到一个全局Facade
if (this.multitonKey == null)
{
throw new Error(Notifier.MULTITON_MSG);
}
return Facade.getInstance(this.multitonKey);
};
SimpleCommand
SimpleCommand: controller
SimpleCommand继承了Notifier类, 可以发送信息。此外,其还有一个execute方法, 可以接受信息。
SimpleCommand.prototype.execute = function (notification) { };
MircoCommand
和SimpleCommand一样继承自Notifier类。但比SimpleCommand多一个subCommands。subCommands是一个SimpleCommand的集合,其中的SimpleCommand的execute顺序遵守FIFO。
MacroCommand.prototype.execute = function(note) // note即是notification
{
while (this.subCommands.length > 0)
{
var ref = this.subCommands.shift();
var cmd = new ref;
cmd.initializeNotifier(this.multitonKey); // 继承自Notifier的函数
cmd.execute(note);
}
};
如果一个逻辑单元可以拆分为多个子逻辑单元,那我们可以继承MacroCommand类,如果一个逻辑单元就可以处理,那我们只需要继承SimpleCommand类。
继承MacroCommand类的子类需要重写initializeMacroCommand方法; 继承SimpleCommand类的子类需要重写execute方法。
示例 (EGER_PRO core.controller)
module game {
export class StartupCommand extends puremvc.MacroCommand {
public constructor(){
super();
}
public initializeMacroCommand():void {
this.addSubCommand(ControllerPrepCommand);
this.addSubCommand(ModelPrepCommand);
this.addSubCommand(ViewPrepCommand);
}
}
}
module game {
export class ControllerPrepCommand extends puremvc.SimpleCommand implements puremvc.ICommand {
public constructor(){
super();
}
public execute(notification:puremvc.INotification):void {
(new SceneManager()).register();
(new MainManager()).register();
//服务器返回command
(new Processor_100_1()).register();
}
}
}
Mediator
Mediator是UI与其他部分的桥梁。
每一个Mediator类的只有一个实例化对象,这些Mediator对象都由facade统一管理。每个Mediator类都有个NAME静态成员,通过NAME属性,可以在facade中找到这个唯一的Mediator对象
Mediator.prototype.mediatorName = null; // 每个Mediator都有唯一的NAME
Mediator.prototype.viewComponent = null; // 该Mediator对象对应的视图组件
Mediator类是继承Notifier类。 同时,Mediator也可以接受消息,它通过listNotificationInterests()方法返回它感兴趣的消息名,当接收到它感兴趣的消息名时,他就会调用handleNotification()方法处理消息。在Mediator子类中,需要重写listNotificationInterests(),handleNotification()方法。
// EGER_PRO view.panel.mediator.MapMediator.ts
module game {
export class MapMediator extends BaseMediator {
public static NAME: string = "MapMediator";
public constructor(viewComponent: any = null) {
super(MapMediator.NAME,viewComponent);
}
public listNotificationInterests(): Array<any> {
return [
PanelNotify.OPEN_MAP,
PanelNotify.CLOSE_MAP
];
}
private mapPanel: MapPanel = new MapPanel();
public handleNotification(notification: puremvc.INotification): void {
var data: any = notification.getBody();
switch(notification.getName()) {
case PanelNotify.OPEN_MAP: {
//显示角色面板
this.showUI(this.mapPanel,false,0,0,5);
break;
}
case PanelNotify.CLOSE_MAP: {
this.closePanel(1);
break;
}
}
}
}
}
此外,其还有onRegister: 在 facade 注册, onRemove: 摆脱facade管理。
Proxy
Proxy: Model, 用来管理应用的数据模型;
其继承了Notifier, 拥有sendNotification方法,但其不具备接受Notification的能力。
Proxy.prototype.proxyName = null; // NAME
Proxy.prototype.data = null; // 其管理的数据
同Mediator,它也有onRegister()/onRemove()方法
View
Proxy/Mediator/Command分别对应MVC中的Model/View/Controller,也分别有对应的单例管理,Model保存所有的Proxy引用、View保存所有的Mediator引用,Controller保存所有的Command映射。
在facade中注册的mediator其实调用了view的registerMediator。
view持有一个observerMap,里面保存了Notification和Observer的对应关系。当我们注册Mediator时,会创建一个observer,将其与Mediator中的notificationName映射起来。
View.prototype.registerMediator = function(mediator)
{
if(this.mediatorMap[mediator.getMediatorName()] != null)
{
return;
}
// mediator类继承Notifier类,这是初始化Notifier,给mediator的facade属性赋值
mediator.initializeNotifier(this.multitonKey);
this.mediatorMap[mediator.getMediatorName()] = mediator;
// 返回mediator感兴趣的消息
var interests = mediator.listNotificationInterests();
// register mediator as an observer for each notification
if(interests.length > 0)
{
// 创建一个Observer,把notification和mediator关联起来
var observer = new Observer(mediator.handleNotification, mediator);
for(var i = 0; i < interests.length; i++)
{
this.registerObserver(interests[i], observer);
}
}
// 在这里调用了mediator的onRegister()方法
mediator.onRegister();
}
View还有一个notifyObservers函数,传入Notification, 然后在observerMap一一找出相应的Observer,然后执行Mediator的handleNotification函数
Controller
类似View, Controller持有一个commandMap,用来保存所有的Command映射。
Controller 可以注册和移除Command。
Model
类似
Facade
Model Controller & View的总代理。对Mediator Proxy 和 Command的操作都可以由他处理。
总结
Proxy: 专注于数据模型
View: 专注于视图
Command: 专注于逻辑