[框架]PureMVC--核心层源码

Model层说明

Model保存对Proxy对象的引用,Proxy负责操作数据模型,与远程服务通信存取数据。这样保证了Model层的可移植性

module puremvc {
    //Model的作用就是保存proxy对象的引用
    export class Model implements IModel {
        proxyMap: Object = null;
        constructor() {
            if (Model.instance)
                throw Error(Model.SINGLETON_MSG);
            Model.instance = this;
            this.proxyMap = {};
            this.initializeModel();
        }
        initializeModel(): void {
        }
        registerProxy(proxy: IProxy): void {
            this.proxyMap[proxy.getProxyName()] = proxy;
            proxy.onRegister();
        }
        removeProxy(proxyName: string): IProxy {
            var proxy: IProxy = this.proxyMap[proxyName];
            if (proxy) {
                delete this.proxyMap[proxyName];
                proxy.onRemove();
            }
            return proxy;
        }
        retrieveProxy(proxyName: string): IProxy {
            return this.proxyMap[proxyName] || null;
        }
        hasProxy(proxyName: string): bool {
            return this.proxyMap[proxyName] != null;
        }
        static SINGLETON_MSG: string = "Model singleton already constructed!";
        static instance: IModel;
        static getInstance(): IModel {
            if (!Model.instance)
                Model.instance = new Model();
            return Model.instance;
        }
    }
}

Proxy Pattern(代理模式)

在很多场合下Proxy需要发送Notification(通知),比如:Proxy从远程服务接收到数据时,发送Notification告诉系统;或当Proxy的数据被更新时,发送Notification告诉系统。

Model通过使用Proxy来保证数据的完整性、一致性。Proxy集中程序的Domain Logic(域逻辑),并对外公布操作数据对象的API。它封装了所有对数据模型的操作,不管数据是客户端还是服务器端的,对程序其他部分来说就是数据的访问是同步还是异步的。

一般来说,Proxy Pattern(代理模式)被用来为控制、访问对象提供一个代理。在基于PureMVC的应用程序,Proxy类被设计用来管理程序数据模型

  • 一个Proxy有可能管理对本地创建的数据结构的访问。它是Proxy的数据对象。在这种情况下,通常会以同步的方式取得或设置数据。Proxy可能会提供访问Data Object部分属性或方法的API,也可能直接提供Data Object的引用。如果提供了更新Data Object的方法,那么在数据被修改时可能会发送一个Notifidation通知系统的其它部分。

  • Remote Proxy被用来封装与远程服务的数据访问。Proxy维护那些与Remote service(远程服务)通信的对象,并控制对这些数据的访问。在这种情况下,调用Proxy获取数据的方法,然后等待Proxy在收到远程服务的数据后发出异步Notification。

Proxy对象不应该通过引用、操作Mediator对象来通知系统,当它的Data Object(数据对象)发生了改变。

它应该采取的方式是发送Notification(这些Notification可能被Command或Mediator响应)。Proxy不关心这些Notification被发出后会影响到系统的什么。
把Model层和系统操作隔离开来,这样当View层和Controller层被重构时就不会影响到Model层

module puremvc {
    //Proxy的作用--保存数据,对数据进行处理,对外提供API
    export class Proxy extends Notifier implements IProxy, INotifier {
        proxyName: string = null;
        data: any = null;
        constructor(proxyName: string = null, data: any = null) {
            super();
            this.proxyName = (proxyName != null) ? proxyName : Proxy.NAME;
            if (data != null)
                this.setData(data);
        }
        getProxyName(): string {
            return this.proxyName;
        }
        setData(data: any): void {
            this.data = data;
        }
        getData(): any {
            return this.data;
        }
        onRegister(): void {
        }
        onRemove(): void {
        }
        static NAME: string = "Proxy";
    }
}

View层说明

View保存对Mediator对象的引用由Mediator对象来操作具体的视图组件(View Component,例如Cocos2d的Layer组件),包括:添加事件监听器,发送或接收Notification ,直接改变视图组件的状态。这样做实现了把视图和控制它的逻辑分离开来

module puremvc {
    export class View implements IView {
        mediatorMap: Object = null;//保存mediator中介者
        observerMap: Object = null;//保存观察者
        constructor() {
            if (View.instance)
                throw Error(View.SINGLETON_MSG);
            View.instance = this;
            this.mediatorMap = {};
            this.observerMap = {};
            this.initializeView();
        }
        initializeView(): void {
        }
        registerObserver(notificationName: string, observer: IObserver): void {
            var observers: IObserver[] = this.observerMap[notificationName];
            if (observers)
                observers.push(observer);
            else
                this.observerMap[notificationName] = [observer];
        }

        removeObserver(notificationName: string, notifyContext: any): void {
            var observers: IObserver[] = this.observerMap[notificationName];

            var i: number = observers.length;
            while (i--) {
                var observer: IObserver = observers[i];
                if (observer.compareNotifyContext(notifyContext)) {
                    observers.splice(i, 1);
                    break;
                }
            }
            if (observers.length == 0)
                delete this.observerMap[notificationName];
        }
        notifyObservers(notification: INotification): void {
            var notificationName: string = notification.getName();

            var observersRef/*Array*/ = this.observerMap[notificationName];
            if (observersRef) {
                // Copy the array.
                var observers/*Array*/ = observersRef.slice(0);
                var len/*Number*/ = observers.length;
                for (var i/*Number*/ = 0; i < len; i++) {
                    var observer/*Observer*/ = observers[i];
                    observer.notifyObserver(notification);
                }
            }
        }
        registerMediator(mediator: IMediator): void {
            var name: string = mediator.getMediatorName();
            //Do not allow re-registration (you must removeMediator first).
            if (this.mediatorMap[name])
                return;
            //Register the Mediator for retrieval by name.
            this.mediatorMap[name] = mediator;

            //Get Notification interests, if any.
            var interests: string[] = mediator.listNotificationInterests();
            var len: Number = interests.length;
            if (len > 0) {
                //Create Observer referencing this mediator's handlNotification method.
                var observer: IObserver = new Observer(mediator.handleNotification, mediator);
                //Register Mediator as Observer for its list of Notification interests.
                for (var i: number = 0; i < len; i++)
                    this.registerObserver(interests[i], observer);
            }
            //Alert the mediator that it has been registered.
            mediator.onRegister();
        }
        retrieveMediator(mediatorName: string): IMediator {
            //Return a strict null when the mediator doesn't exist
            return this.mediatorMap[mediatorName] || null;
        }
        removeMediator(mediatorName: string): IMediator {
            // Retrieve the named mediator
            var mediator: IMediator = this.mediatorMap[mediatorName];
            if (!mediator)
                return null;

            //Get Notification interests, if any.
            var interests: string[] = mediator.listNotificationInterests();

            //For every notification this mediator is interested in...
            var i: number = interests.length;
            while (i--)
                this.removeObserver(interests[i], mediator);

            // remove the mediator from the map
            delete this.mediatorMap[mediatorName];

            //Alert the mediator that it has been removed
            mediator.onRemove();
            return mediator;
        }
        hasMediator(mediatorName: string): bool {
            return this.mediatorMap[mediatorName] != null;
        }
        static SINGLETON_MSG: string = "View singleton already constructed!";
        static instance: IView;
        static getInstance(): IView {
            if (!View.instance)
                View.instance = new View();
            return View.instance;
        }
    }
}

Mediator Pattern(中介者模式)

当用View注册Mediator时,Mediator的listNotifications方法会被调用,以数组形式返回该Mediator对象所关心的所有Notification。
之后,当系统其它角色发出同名的Notification(通知)时,关心这个通知的Mediator都会调用handleNotification方法并将Notification以参数传递到方法

Mediator是视图组件与系统其他部分交互的中介,侦听View Component来处理用户动作和Component的数据请求。Mediator通过发送和接收Notification来与程序其他部分通信。

Mediator保存了一个或多个View Component的引用,通过View Component自身提供的API管理它们。一个View Component应该把尽可能自己的状态和操作封装起来,对外只提供事件、方法和属性的简单的API

Mediator的主要职责是处理View Component派发的事件和系统其他部分发出来的Notification(通知)。因为Mediator也会经常和Proxy交互,所以经常在Mediator的构造方法中取得Proxy实例的引用并保存在Mediator的属性中,这样避免频繁的获取Proxy实例

Mediator负责处理与Controller层、Model层交互,在收到相关Notification时更新View Component。

module puremvc {
    export class Mediator extends Notifier implements IMediator, INotifier {
        mediatorName: string = null;//外部通过中介者名来获取其对象
        viewComponent: any = null;//保存UI组件,便于操作UI接口
        constructor(mediatorName: string = null, viewComponent: any = null) {
            super();
            this.mediatorName = (mediatorName != null) ? mediatorName : Mediator.NAME;
            this.viewComponent = viewComponent;
        }
        getMediatorName(): string {
            return this.mediatorName;
        }
        getViewComponent(): any {
            return this.viewComponent;
        }
        setViewComponent(viewComponent: any): void {
            this.viewComponent = viewComponent;
        }
        //注册mediator到单例view中时,会调用下面两个函数,遍历消息名来注册消息处理回调函数。
        listNotificationInterests(): string[] {
            return new string[];
        }
        handleNotification(notification: INotification): void {
        }
        onRegister(): void {
        }
        onRemove(): void {
        }
        static NAME: string = 'Mediator';
    }
}

Controller层说明

Controller保存所有Command的映射。

module puremvc {
    export class Controller implements IController {
        //保存单例view对象,当保存/移除通知命令时,单例view对象也进行注册/注销观察者。
        view: IView = null;

        commandMap: Object = null;//保存命令对象引用
        constructor() {
            if (Controller.instance)
                throw Error(Controller.SINGLETON_MSG);

            Controller.instance = this;
            this.commandMap = {};
            this.initializeController();
        }
        initializeController(): void {
            this.view = View.getInstance();
        }
        executeCommand(notification: INotification): void {
            var commandClassRef: any = this.commandMap[notification.getName()];
            if (commandClassRef) {
                var command: ICommand = <ICommand> /*</>*/ new commandClassRef();
                command.execute(notification);
            }
        }
        registerCommand(notificationName: string, commandClassRef: Function): void {
            if (!this.commandMap[notificationName])
                this.view.registerObserver(notificationName, new Observer(this.executeCommand, this));

            this.commandMap[notificationName] = commandClassRef;
        }
        hasCommand(notificationName: string): bool {
            return this.commandMap[notificationName] != null;
        }
        removeCommand(notificationName: string): void {
            // if the Command is registered...
            if (this.hasCommand(notificationName)) {
                this.view.removeObserver(notificationName, this);
                delete this.commandMap[notificationName];
            }
        }
        static instance: IController;
        static SINGLETON_MSG: string = "Controller singleton already constructed!";
        static getInstance(): IController {
            if (!Controller.instance)
                Controller.instance = new Controller();
            return Controller.instance;
        }
    }
}

Command Pattern(命令模式)

Command对象是无状态的;只有在需要的时候(Controller收到相应的Notification)才会被创建,并且在被执行(调用execute方法)之后就会被删除。所以不要在那些生命周期长的对象(long-living object)里引用Command对象。
Command可以获取Proxy对象并与之交互,发送Notification,执行其他的Command。经常用于复杂的或系统范围的操作,如应用程序的“启动”和“关闭”。应用程序的业务逻辑应该在这里实现。

Controller会注册侦听每一个Notification,当被通知到时,Controller会实例化一个该Notification对应的Command类的对象。最后,将Notification作为参数传递给execute方法

Command要实现ICommand接口。在PureMVC中有两个类实现了ICommand接口:SimpleCommand、MacroCommand。SimpleCommand只有一个execute方法,execute方法接受一个Inotification实例做为参数。实际应用中,你只需要重写这个方法就行了。MacroCommand让你可以顺序执行多个Command。每个执行都会创建一个Command对象并传参一个对源Notification的引用

MacroCommand在构造方法调用自身的initializeMacroCommand方法。实际应用中,你需重写这个方法,调用addSubCommand添加子Command。你可以任意组合SimpleCommand和MacroCommand成为一个新的Command

module puremvc {
    export class SimpleCommand extends Notifier implements ICommand, INotifier {
        execute(notification: INotification): void {
        }
    }
}

module puremvc {
	export class MacroCommand extends Notifier implements ICommand, INotifier {
		subCommands: Function[] = null;
		constructor() {
			super();
			this.subCommands = new Function[]();
			this.initializeMacroCommand();
		}
		initializeMacroCommand(): void {
		}
		addSubCommand(commandClassRef: Function): void {
			this.subCommands.push(commandClassRef);
		}
		execute(notification: INotification): void {
			var subCommands: Function[] = this.subCommands.slice(0);
			var len: number = this.subCommands.length;
			for (var i: number = 0; i < len; i++) {
				var commandClassRef: any = subCommands[i];
				var commandInstance: ICommand = <ICommand> /*</>*/ new commandClassRef();
				commandInstance.execute(notification);
			}
			this.subCommands.splice(0);
		}
	}
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页