新聞中心
.NET程序設(shè)計不光是對于Visual Studio 2010這樣的工具使用上,或者一些小技巧。還包括一些設(shè)計理念和設(shè)計規(guī)則,這些反而是促進程序員進步的源泉。

之前寫了一篇名稱為《談談關(guān)于MVP模式中V-P交互問題》的文章,主要表達本人對于MVP模式下(主要針對Passive View變體)View和Presenter之間的關(guān)系,以及它們之間的交互應該采用怎樣的原則和方式的看法。園子里的朋友對此展開了一些討論,尤其是是一個叫做非空的朋友轉(zhuǎn)述了另一篇文章提出的關(guān)于CAB中關(guān)于MVP模式的14條規(guī)則,和本人的觀點有很多相似之處,當然也有一些不一致的地方。為此,在本篇文章中,就此進行一些必要的補充。
一、CAB(Componsable Application Block)基于14條MVP規(guī)則
為了讓所有的人都能夠閱讀上面提及的那篇文章,我將其轉(zhuǎn)載我個人的博客中,有興趣的讀者可以仔細閱讀(《Design Rules for Model-View-Presenter》)。文章作者提出的觀點和我在《談談關(guān)于MVP模式中V-P交互問題》中的觀點是一致的,即Presenter對于View應該是相對透明的,View不能直接對Presenter進行操作,目的是實現(xiàn)Presenter和View之間的分離(The generated code is not quite as I would like it, I prefer that the view has no knowledge of the presenter and no direct access to it either as this gives a cleaner separation between views and presenters)。文章作者傾向采用事件注冊的方式實現(xiàn)Presenter和View,不過我不太清楚具體是注冊View還是Presenter的時間。在《談談關(guān)于MVP模式中V-P交互問題》中對MVP的實現(xiàn)手段,我采用的是在Presenter注冊View的事件。關(guān)于View和Presenter的分離,我的做法作得更加徹底一點——根本就不給開發(fā)者從View調(diào)用Presenter的機會。
文中提出了關(guān)于CAB的14條編寫符合MVP規(guī)范的規(guī)則,在這里我特將其翻譯成中文:
1、所有的View(包括View的接口)的名稱應該以View作為后綴,比如TaskView/ITaskView;
2、所有的Presenter名稱應該以Presenter作為后綴,比如TaskViewPresenter;
3、Presenter完成Use Case處理邏輯,對GUI控件的處理應該在View中實現(xiàn);
4、View調(diào)用Presenter的方法應該像觸發(fā)事件異常,通過調(diào)用OnXxx方法的方式來實現(xiàn);
5、應該盡可能地限制View對Presenter的調(diào)用,并且調(diào)用的方式限于按照“事件”的形式,比如_presenter.OnViewReady();
6、View不允許通過Presenter直接調(diào)用Model和Service,并且Presenter的方法應該是不具有返回值的;
7、Presenter必須通過View接口的方式調(diào)用View
8、除了對View接口成員的實現(xiàn)外,View中的其他方法不應該是public的;
9、除了CAB ModuleController 對View的加載和限制外,View只能被Presenter調(diào)用;
10、View接口方法應該基于Use Case的邏輯起一個有意義的名稱,比如SetDataSource這樣的方法名稱是不合法的;
11、View接口的成員應該僅限于方法,不應該包含屬性;
12、所有的數(shù)據(jù)應用保持在Model中
13、定義在View接口的方法不應該包含對GUI空間名稱的引用(比如AddExplorerBarGroup),因為這會使Presenter知道View太多關(guān)于實現(xiàn)方面的細節(jié);
14、盡量讓View的方法名稱反映Use Case的業(yè)務邏輯,這樣可以使你的代碼具有自表述性并更加易于理解。
再次回到《談談關(guān)于MVP模式中V-P交互問題》中討論的話題,在我看來,拋開1和2對View的Presenter命名的規(guī)范外,其余的12條規(guī)則體現(xiàn)了MVP關(guān)于View和Presenter之間應該具有的關(guān)系,以及我們應該采取的正確的Presenter和View交互方式。View和Presenter之間的關(guān)系,可以通過對Presenter的角色界定來體現(xiàn),在整個MVP體系中Presenter扮演的是協(xié)調(diào)者的角色。
二、Presenter是協(xié)調(diào)者,是整個MVP體系的控制中心
如果我們將MVP體系比喻成一個社團(考慮到中國沒有黑社會,這里我們說社團),我們經(jīng)??匆姷耐悄切┰谕饷娼哟娜?,你可以將它們看成是View。也就是說View是和外界打交道的人,是行動者,就像是到處砍人、收保護費,以及和別的社團搶地盤的都是這些處于社團基層的小混混一樣。View永遠處于處于幕前,和最終用戶進行交互,但是地位卻不高。對于用戶的UI交互請求該如何進行處理,View做不了主,它需要向大佬匯報。所以View永遠不可能是決策者,僅僅是一個匯報者而已。
Presenter才是真正的大佬、話事人,執(zhí)龍頭杖的。Presenter生藏不露,最終用戶感知不但它的存在,就像社團大哥大都隱藏的比較好,甚至以政府官員(比如文強大哥)或者是電影公司老板(比如香港的XXX電影公司)的身份出現(xiàn)。但是,我們知道,他才是整個社團的主導、核心,是整個事務的決策者和執(zhí)行者,使能夠調(diào)動相關(guān)資源的協(xié)調(diào)者,而這個事務,你可以理解為Use Case。也就是說,Presenter是對Use Case的反映,UI交互邏輯的處理流程定義在Presenter中,但是具體的實現(xiàn)并不是完全在Presenter中,這一點很重要,下面一節(jié)中我們還會談到。
我們還是把話題回到交互上面。這里的交互,即View和Presenter之間如果溝通,是比較特別的。談到溝通,很多人都會認為這是一個雙向的問題,而View和Presenter采用單向的溝通方式,這和某些上下級的溝通方式有點類似——下級單方地向上級匯報工作,上級單方的向下級下達命名。這在等級觀念深重社團中更是如此,我們習慣的場景是這樣的:小混混向大佬說:“我們的場子昨天晚上被砸了,懷疑是XXX干的”。大佬說:“恩,知道了,下去吧!”。真正有前途的小混混不會說“我們的場子昨天晚上被砸了,懷疑是XXX干的,我們什么時候去砍他?”。真正有范兒的大佬不會馬上命令你在什么時候、什么地點、帶多少兄弟去砍人,而在計劃實施的時候會向相關(guān)成員下達砍人的指令。
反映在真正View|Presenter的交互上面,就是說:View單純地將用戶的交互請求匯報給Presenter;Presenter接收到請求之后,整合相應的資源、執(zhí)行相應的處理邏輯。對處理流程的某一個步驟,如果設(shè)置到業(yè)務邏輯和數(shù)據(jù)模型,則調(diào)用Model,如果涉及到對GUI控件的操作,還會調(diào)用View。View將交互請求遞交給Presenter之后,不需要考慮后續(xù)需要做什么,因為Presenter會在適當?shù)臅r候命令View該如何做。
所以說,Presenter是整個體系的驅(qū)動著,View和Presenter不應該是一種拉的關(guān)系,而是一種推的關(guān)系。View將用戶交互請求推給Presenter,Presenter將數(shù)據(jù)推給View并驅(qū)動View完成相應的UI相應。 正因為如此,上面的MVP規(guī)則列表中才規(guī)定Presenter的方法不需要返回值,View的接口不需要定義屬性。實際在我個人看來,Presenter和View接口都應該只包含返回類型為void的方法即可。
三、Presenter不關(guān)注具體的實現(xiàn)細節(jié)
談到這里有人會說,所有的關(guān)于UI處理邏輯定義在Presenter中,那么會不會使Presenter變得臃腫不堪呢?持這種觀點的人實際上走入了另外一個誤區(qū)。我曾經(jīng)看到過有人寫過這樣一個極端的例子——將View的所有控件都以屬性的方式公布出來,定義在View接口中,所有控件相關(guān)的操作都實現(xiàn)在Presenter中。很明顯這是不對的,雖然這個例子很極端,但是我想很多對MVP不是太了解的人或多或少會犯這種錯誤。
在上面一節(jié)中,我們說過UI交互邏輯的處理流程定義在Presenter中,但是具體的實現(xiàn)并不是完全在Presenter中。Presenter是藍圖的設(shè)計者,并不關(guān)注實現(xiàn)的細節(jié)。大佬只是制定行動計劃,真正砍人、收保護費和搶地盤這種操作性強的工種的還是屬于小混混們。
所以該View干的事一件也逃不了,只是View不考慮什么時候干,因為Presenter會在適當?shù)臅r候通知你,View得保證隨叫隨到。為了保證Presenter能夠有效地控制View,需要將這些操作定義在接口中。既然定義在接口中,操作的粒度就不能太細。Presenter關(guān)于的是整個Use Case的處理流程,所以定義在View接口中的操作也應該采用處理流程相關(guān)的語言來定義。
文章名稱:詳解MVP模式的十四條清規(guī)戒律
分享網(wǎng)址:http://m.fisionsoft.com.cn/article/djciosd.html


咨詢
建站咨詢
