PMVC使用實戰(zhàn)
按照之前的學習記錄整理方法,這一次我也會將pmvc的學習記錄整理成知識點和實踐兩個部分,可能會有效果展示部分.
1.知識點
主管給了一份寫的很清晰的文檔,我只能是簡單總結一下了
1.1PMVC概述
PureMVC,下稱PMVC,是一個MVC框架.MVC是Model-View-Controller的縮寫,這是一個經(jīng)常使用的架構.大二暑假做高科實習的時候做web后端開發(fā)就是用的SpringMVC,當時只是停留在會使用的表面.
MVC的目的是分離數(shù)據(jù)層/表現(xiàn)層和邏輯層,降低耦合性
PMVC將應用程序分為三層四個模塊:Model,View,Controller,每一層的具體實現(xiàn)都是一個單例,第四個模塊facade負責各層之間的通信
1.2Facade
Facade初始化Model,View,Controller,三個單例,并且能訪問各層類的public方法,上面說到這四個模塊的實現(xiàn)都是單例,facade就是負責實例化另外三個單例的,它是整個框架的最上層,同時也負責MVC三個模塊的通信.Facade的設計是一個典型的外觀模式(畢竟它都叫"Facade-表面"這個名字了)
實際使用時,開發(fā)者繼承一個Facade,添加自己需要的屬性和方法,然后就可以開始用了.
1.3觀察者模式
觀察者模式是一個設計模式,也是facade主要用到的設計模式.引用菜鳥教程上的解釋:
觀察者模式是一種行為型設計模式,它定義了一種一對多的依賴關系,當一個對象的狀態(tài)發(fā)生改變時,其所有依賴者都會收到通知并自動更新。
當對象間存在一對多關系時,則使用觀察者模式(Observer Pattern)。比如,當一個對象被修改時,則會自動通知依賴它的對象。觀察者模式屬于行為型模式。
PMVC封裝了一個方法Notification來從M,V,C發(fā)送通知,用來觸發(fā)執(zhí)行命令,這套機制的實現(xiàn)由PMVC實現(xiàn),我們不需要具體的了解
1.4(重要)PMVC中組件的耦合與依賴關系
command command的權限很高,但它的創(chuàng)建是被限制的.
command可以發(fā)送Notification給其他組件,可以直接獲取和操作mediator和proxy,可以注冊銷毀和檢查proxy,mediator和command;
mediator mediator主要做三件事:修改自己的視圖組件,檢查或修改proxy的屬性(這點很重要,牢記medaitor可以操控proxy修改proxy) ,發(fā)送notification給其他mediator或者command(重要,牢記proxy不接收消息)
proxy proxy可能專門管理一個本地創(chuàng)建的復雜的數(shù)據(jù)對象,也可以理解為,proxy封裝了一個數(shù)據(jù)對象.
1.5我對model&proxy,view&mediator,controller&command的理解
這三組東西似乎總是兩兩綁定,我一直不理解具體用的時候是個什么關系,比如說,我設計模塊的時候,model/view/controller是要單獨寫個類出來嗎還是說和對應的proxy/mediator/command綁在一起.
現(xiàn)在我覺得,m/v/c三個東西是相對抽象的,它們有具體的憑依的模塊,舉例來說,一般會寫一個data類描述某個模塊,在fgui里面,一個繼承Gcomponent的組件類就是view,但是它們的管理是由pro/med/com三個層級管理者來執(zhí)行的,mvc三個模塊完全依賴于各自的管理者.從這個角度來說,我甚至不用單獨寫個data類,反正data的屬性完全封裝,即使單獨寫類也不會給除了proxy以外的任何模塊使用.
2.案例分析
找到一個csdn用戶"嘿呀好氣"的簡單教程,按理說已經(jīng)簡單到不需要做記錄了,但是我畢竟是個新手,簡單寫寫有助于理解
地址
https://blog.csdn.net/kirikayakazu/article/details/89788451
結構上分為以下幾個內(nèi)容:
實體類
Proxy
Mediator
Command
Facade
繼承component的腳本組件
我的疑問:既然proxy對應了model層,為什么還要有單獨的實體類,把他們放在一起可以嗎,這樣做應該是為了降低耦合,不過實體類應該只依賴于proxy才對,沒必要降低耦合.
emm還是有必要的,這樣結構更清晰,可讀性強
實體類 存放一格模塊/對象的描述,不用解釋
Proxy model層的數(shù)據(jù)操縱類,能夠直接處理實體類,在這里要做:
注冊該模塊名字:繼承屬性proxyName
設置單例和單例獲取的方法getInstance();
構造函數(shù);
實體處理函數(shù);
Mediator 表現(xiàn)層管理類,似乎沒有和View組件分離的必要,在這里要做:
單例和獲取單例方法
構造函數(shù)(注冊UI組件的邏輯在這里進行);
監(jiān)聽回調(diào)函數(shù),主要做發(fā)送消息(Notification)的工作;
注冊感興趣的消息(notification):繼承函數(shù)listNotificationInterests();
消息處理函數(shù);
Command 控制層管理類
單例和獲取單例方法
邏輯處理函數(shù):execute(notification:puremvc.INotification)
Facade 架構的最上層.管理mvc三層
單例和獲取單例
構造函數(shù),其中要做:注冊三個層級的單例.
3.實戰(zhàn):使用PMVC重構cocos小游戲《圍住神經(jīng)貓》
之前已經(jīng)進行過一次cocos開發(fā)了,因為使用和加載資源的方式?jīng)]變(還是fgui)所以不再贅述
先前項目記錄:
https://www.bilibili.com/read/cv25420626
相比之前,有了一些進步:
既然使用了MVC框架,代碼結構耦合度肯定是更低了,結構也更加分明(但是明顯復雜了)
進一步優(yōu)化了代碼,原先的一些模塊在拆分結構以后發(fā)現(xiàn)居然沒用了,這說明之前肯定是有冗余的
這次重構給我的感覺是:結構反而變復雜了.項目的模塊變多了不少,以至于我可能需要畫張圖來表現(xiàn)我這個項目的mvc架構是怎么樣的.
圖樣如下:

Proxy :
ProxyGameScene管理游戲有關的私有核心數(shù)據(jù)(公共數(shù)據(jù)寫在靜態(tài)數(shù)據(jù)類中,可被自由訪問),即GameData,包含dataMatrix和cat數(shù)據(jù)等
Mediator
MediatorMainMenu負責主菜單的界面,獲取資源,添加按鈕監(jiān)聽并且可以處理loadscene的消息,也可以發(fā)送loadscene消息
MediatorGame,負責游戲主邏輯,可以處理loadscene和resetgame消息,可以發(fā)送loadscene,findpath消息
MediatorDialog,負責勝利或失敗對話框的邏輯,可以處理showdialog消息,可以發(fā)送loadscene,resetgame消息
Command
loadsceneCommand決定加載哪個場景(因為我不再使用多場景,所以這里說的是加載哪個場景的UI界面),加載完后會發(fā)送resetscene消息,使得舞臺初始化
ResetGameCommand發(fā)送重置游戲的消息,使得游戲場景更新關卡,并初始化關卡
CommandShowDiaBox決定加載哪個對話框,然后給MediatorDialog發(fā)送消息,加載對話框
CommandFindPath最復雜的一個command,要在玩家點擊以后,根據(jù)ProxyGameScene的數(shù)據(jù)變化求出貓的狀態(tài),游戲進行狀態(tài)和貓的下一個落點等一些列數(shù)據(jù).
現(xiàn)在看看我是怎么做的
3.1構建Facade類和啟動器
眾所周知cocos是基于節(jié)點運作的,除非是靜態(tài)類或者是被別的腳本new出來,不然要把腳本掛載到節(jié)點上才能實例化.Facade肯定不能繼承腳本類cc.Component,所以要有一個啟動器把他實例化出來
初始化類,順便在這里以靜態(tài)的方式提前加載資源包

我的Facade類:AppFacade繼承了Facade,并在此之上添加我的邏輯,主要是注冊消息名稱和三個層級的模塊\


3.2 Proxy和Data(在這里用data類封裝了抽象的model)
首先是Data,這里的data內(nèi)容非常少,這也是我拆分架構以后才發(fā)現(xiàn)的,這個小游戲用到的數(shù)據(jù)其實是非常少的

然后是Proxy,Proxy只提供了一些操縱數(shù)據(jù)的方法供外部調(diào)用.


為什么這里只有一個Proxy,而mediator卻有三個,這是因為主界面和對話框的Mediator幾乎沒有任何數(shù)據(jù)可言,就是純UI界面,所以完全不需要Proxy來管理數(shù)據(jù).
3.3 Mediator
這里只以MediatorGame為例,因為正如上面所說,另外兩個Mediator太簡單了.
可以看到mediator的成員都是視圖組件
可以看到Mediator能夠發(fā)送和接收消息,并根據(jù)不同的消息作處理
3.4Command
Command只有在使用的時候才會出現(xiàn),使用完畢以后會消失,command和notification是一對一的關系,一個command不能綁定多個消息,一個消息也不能被多個command綁定,否則會有一個不監(jiān)聽消息.
command不需要調(diào)用,因為它是和消息綁定的,所以想要執(zhí)行command,直接發(fā)送對應的消息就可以
command有一個繼承方法execute,它會在command被激活是調(diào)用,這也是command的核心方法.
最后效果不再演示,和先前是一樣的