puremvc中把系统分成3部分,controller view model相互分离,通过notification进行各个部分的通信,这个通信是如何进行的呢。 我们知道,在Mediator、Proxy和Command中,可以调用sendNotification触发注册的Command和Mediator,那么sendNotification以后是怎么触发注册的Command和Mediator的? 首先看一下notification的结构: notification实现INotification接口,存储三个属性name,body,type sendNotification这个方法是INotifier这个接口中的,看下实现这个方法的类Notifier的中这个方法的定义 public function sendNotification( notificationName:String, body:Object=null, type:String=null ):void { facade.sendNotification( notificationName, body, type ); } 实际上是调用facde的sendNotification 看一下facade的这个方法 public function sendNotification( notificationName:String, body:Object=null, type:String=null ):void { notifyObservers( new Notification( notificationName, body, type ) ); } 这里创建了一个Notification对象,接着往下看 public function notifyObservers ( notification:INotification ):void { if ( view != null ) view.notifyObservers( notification ); } 这里实际上是view调用notifyObservers,将刚才新建的notification传入,看一下这个方法 public function notifyObservers( notification:INotification ) : void { if( observerMap[ notification.getName() ] != null ) { var observers_ref:Array = observerMap[ notification.getName() ] as Array; var observers:Array = new Array(); var observer:IObserver; for (var i:Number = 0; i < observers_ref.length; i++) { observer = observers_ref[ i ] as IObserver; observers.push( observer ); } for (i = 0; i < observers.length; i++) { observer = observers[ i ] as IObserver; observer.notifyObserver( notification ); } } } 这里在view中将注册的command和mediator放在observer 数组中,并用名字来进行了索引,最终调用的是 observer.notifyObserver( notification ); 来看一下是怎么注册的,我们可以使用facade的registerXXX来注册Command和Mediator以及Proxy,其中Proxy并不接收Notification,那么来看一下, 先看Command public function registerCommand( notificationName:String, commandClassRef:Class ):void { controller.registerCommand( notificationName, commandClassRef ); } 这里实际上调用的是 controller.registerCommand方法,继续追踪 public function registerCommand( notificationName : String, commandClassRef : Class ) : void { if ( commandMap[ notificationName ] == null ) { view.registerObserver( notificationName, new Observer( executeCommand, this ) ); } commandMap[ notificationName ] = commandClassRef; } 这里最终调用的是view.registerObserver方法,创建了Observer,并通过notificationName来索引这个Observer,那么observer是什么呢 来看一下Observer的构造函数 public function Observer( notifyMethod:Function, notifyContext:Object ) { setNotifyMethod( notifyMethod ); setNotifyContext( notifyContext ); } 这里Observer保存的是上面controller类的executeCommand方法,和controller对象, 上面已经提到了,最终sendNotification是通过observer.notifyObserver( notification );这个方法执行的,那么这个方法具体干了什么呢 public function notifyObserver( notification:INotification ):void { this.getNotifyMethod().apply(this.getNotifyContext(),[notification]); } 这里调用刚才保存的方法,并传递notification对象,这里本质上是调用了 controller.executeCommand(notification), public function executeCommand( note : INotification ) : void { var commandClassRef : Class = commandMap[ note.getName() ]; if ( commandClassRef == null ) return; var commandInstance : ICommand = new commandClassRef(); commandInstance.execute( note ); } 在这里创建了command类的实例,并调用了execute方法,将notification对象传入。 所以最终sendNotification是通过名字找到具体的command类,并创建实例,并执行 以上是command的执行过程。 再来看看Mediator的注册 public function registerMediator( mediator:IMediator ):void { if ( view != null ) view.registerMediator( mediator ); } view: public function registerMediator( mediator:IMediator ) : void { if ( mediatorMap[ mediator.getMediatorName() ] != null ) return; mediatorMap[ mediator.getMediatorName() ] = mediator; var interests:Array = mediator.listNotificationInterests(); if ( interests.length > 0 ) { var observer:Observer = new Observer( mediator.handleNotification, mediator ); for ( var i:Number=0; i<interests.length; i++ ) { registerObserver( interests, observer ); } } mediator.onRegister(); } 这里仍然是创建observer,保存mediator.handleNotification和mediator对象 那么sendNotification以后,通过mediator的listNotificationInterests数组中的名字,来索引到对应的Observer, public function notifyObserver( notification:INotification ):void { this.getNotifyMethod().apply(this.getNotifyContext(),[notification]); } 这里本质调用了mediator.handleNotification,并传入参数notification对象。 综上所述,sendNotification实际上是通过名字来索引到对应的Observer,由Observer调用注册的Controller对象的executeCommand方法或者Mediator对象的handleNotification方法。 |