PureMVC(JS版)源碼解析(九):View類

     在講解View類以前,咱們先回顧一下PureMVC的模塊劃分:數組

     在PureMVC中M、V、C三部分由三個單例類管理,分別是Model/View/Controller。PureMVC中另一個單例類——Facade。Facade提供了與MVC三個單例類(核心類)通訊的惟一接口。這4個單例類構建了PureMVC的骨架。
     在遊戲開發中,一個遊戲是由多個模塊組成,如主場景模塊,戰鬥模塊等等,每一個模塊一般都是單獨的Model/View/Controller,顯然PureMVC的4個單例類是沒法知足需求的,它就提供了Proxy/Mediator/Command來解決問題。
     Proxy/Mediator/Command分別對應MVC中的Model/View/Controller,也分別有對應的單例管理,Model保存全部的Proxy引用、View保存全部的Mediator引用,Controller保存全部的Command映射。
     這篇博客開始,咱們就要開始講解PureMVC的三大核心類,先看看View類。
     View保存了全部的Mediator引用,它有一個mediatorMap數組,用來存放全部的Mediator引用。
View.prototype.mediatorMap = null;

     咱們知道Mediator類有一個onRegister()方法,當Mediator對象在facade中註冊時調用的,實際上Mediator對象的註冊是經過調用View單例的registerMediator()方法來實現。函數

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();
}

從這段代碼中能夠明白Mediator類onRegister()方法的調用機制了,這段代碼中還有一個地方須要咱們去深刻研究:this

//這段代碼什麼意思呢?
this
.registerObserver(interests[i], observer);

registerObserver(),經過方法名咱們能夠知道它是用來註冊Observer對象的,咱們看一下的實現代碼:spa

View.prototype.registerObserver = function(notificationName, observer)                 
{                                                                                      
    if(this.observerMap[notificationName] != null)                                     
    {                                                                                  
        this.observerMap[notificationName].push(observer);                             
    }                                                                                  
    else                                                                               
    {                                                                                  
        this.observerMap[notificationName] = [observer];                               
    }                                                                                  
};                                                                                     

View類的observerMap屬性主要用於存放消息名(notificationName)和observer(觀察者)之間的映射,一個消息名能夠對應幾個observer,因此若是檢索到observerMap中存在notificationName,則把observer推入相應的數組中。observerMap大體的數據格式以下:
{「notificationName1":[observer1,observer2],"notificationName2":[observer3,observer4]} 
 
同時,除了註冊觀察者【registerObserver()】,還須要從observerMap中移除觀察者(removeObserver):
View.prototype.removeObserver = function(notificationName, notifyContext)  
{                                                                          
    //經過notificationName,能夠檢索到接受該消息的Observer,返回一個數組                                                                
    var observers = this.observerMap[notificationName];                    
    for(var i = 0; i < observers.length; i++)                              
    {                                                                      
        if(observers[i].compareNotifyContext(notifyContext) == true)       
        {      
            //移除observer                                                            
            observers.splice(i, 1);                                        
            break;                                                         
        }                                                                  
    }                                                                                                                                   
    if(observers.length == 0)                                              
    {                                                                      
        delete this.observerMap[notificationName];                         
    }                                                                      
};                                                                         

 

     另外,咱們知道Mediator類還有一個與onRegister()(註冊)方法對應的onRemove()(註銷)方法,是Mediator對象在facade中註銷時調用的,Mediator對象的註銷是經過調用View單例的removeMediator()方法來實現:prototype

View.prototype.removeMediator = function(mediatorName)                      
{                                                                           
    var mediator = this.mediatorMap[mediatorName];                          
    if(mediator)                                                            
    {                                                                       
        // for every notification the mediator is interested in...          
        var interests = mediator.listNotificationInterests();               
        for(var i = 0; i < interests.length; i++)                           
        {                                                                   
            // remove the observer linking the mediator to the notification                                               
            this.removeObserver(interests[i], mediator);                    
        }                                                                   
                                                                            
        // remove the mediator from the map                                 
        delete this.mediatorMap[mediatorName];                              
                                                                            
        //觸發mediator對象的onRemove方法                  
        mediator.onRemove();                                                
    }                                                                       
                                                                            
    return mediator;                                                        
};                                                                          

     mediator對象除了在facade中註冊(registerMediator),從facade中註銷(removeMediator),還有一個很重要的方法,就是從facade裏面檢索mediator( retrieveMediator):設計

View.prototype.retrieveMediator = function(mediatorName)             
{                                                                    
    return this.mediatorMap[mediatorName];                           
};                                                                                                                                     

     經過上面的例子,咱們能夠知道Mediator類onRegister(),onRemove()方法的使用原理(與View類的registerMediator(),removeMediator,retrieveMediator()對應)和怎麼註冊觀察者(registerObserver())、怎麼移除觀察者(removeMediator())。View類還有一個重要的方法就是給全部的觀察者發送消息(notifyObservers()),觸發觀察者的消息處理函數。rest

View.prototype.notifyObservers = function(notification)
{
    // SIC
    if(this.observerMap[notification.getName()] != null)
    {
        var observers_ref = this.observerMap[notification.getName()], observers = [], observer

        for(var i = 0; i < observers_ref.length; i++)
        {
            observer = observers_ref[i];
            observers.push(observer);
        }

        for(var i = 0; i < observers.length; i++)
        {
            observer = observers[i];
            //出發了觀察者的消息處理函數
            observer.notifyObserver(notification);
        }
    }
};

      到目前爲止,咱們應該能夠大體弄清楚mediator對象的消息處理機制了。code

      咱們在Mediator/Command/Proxy經過調用繼承自Notifier類的sendNotification()發送消息,其實是調用View單例的notifyObservers()方法。server

 

     View類是個多例類,它用instanceMap來存放View類的實例,咱們來看一下它的構造函數:xml

function View(key)
{
    if(View.instanceMap[key] != null)
    {
        throw new Error(View.MULTITON_MSG);
    };

    this.multitonKey = key;
    View.instanceMap[this.multitonKey] = this;
    this.mediatorMap = [];
    this.observerMap = [];
    this.initializeView();
};

/**
 * @protected
 * Initialize the Singleton View instance
 * 
 * Called automatically by the constructor, this is your opportunity to
 * initialize the Singleton instance in your subclass without overriding the
 * constructor
 * 
 * @return {void}
 */
View.prototype.initializeView = function()
{
    return;
};

 

     根據Multiton模式(Multiton模式不理解的能夠自行搜索)的設計原理,咱們能夠經過一個key值調用getInstance()方法來獲取某個View實例:
View.getInstance = function(key)
{
    if (null == key)
        return null;
        
    if(View.instanceMap[key] == null)
    {
        View.instanceMap[key] = new View(key);
    };
//其實是從instanceMap數組中檢索
return View.instanceMap[key]; };

 

       總結一下,View類的結構相對於Mediator、Command、Proxy類要複雜許多,但他是PureMVC消息機制的核心,裏面的不少方法咱們須要記住,反覆揣摩,特別是notifyObservers()。最後,附上View類的思惟導圖。

相關文章
相關標籤/搜索