1.詳細功能
- 能夠控制整個X-gen的調(diào)用過程堪澎,并能夠靈活地擴展這個調(diào)用過程
- 調(diào)用theme提供的Action來具體實現(xiàn)每一個需要生成的功能
- 能夠在每個Action執(zhí)行前后,動態(tài)組合添加一些功能
- 能很靈活地通知多個輸出實現(xiàn)锭硼,并能實現(xiàn)調(diào)用模塊和輸出模塊的解耦
2.功能邊界
- 只負責具體的generate調(diào)用過程
- 不關(guān)心generate的數(shù)據(jù)從何而來
- 不關(guān)心實際如何generate
- 不關(guān)心按照什么流程順序來generate
- 不關(guān)心每個步驟都需要完成些什么功能,那都不是固定的,完全可以通過配置或者是開發(fā)人員在外部theme中來定
3.對外的接口
4.內(nèi)部實現(xiàn)
實現(xiàn)的起點
為了讓大家更好的理解調(diào)用模塊的內(nèi)部實現(xiàn)架構(gòu)芹橡,因此先以一個最簡單的實現(xiàn)結(jié)構(gòu)為起點讥耗,采用重構(gòu)的方式有勾,逐步把相關(guān)的設(shè)計模式應(yīng)用進來,從簡單到復(fù)雜古程,從而讓大家更好的看到如何選擇要使用的設(shè)計模式蔼卡、如何實際應(yīng)用設(shè)計模式以及如何讓多種設(shè)計模式協(xié)同工作。
1.針對前面定義的API挣磨,提供一個最基本的實現(xiàn)雇逞。其實,真正調(diào)用的實現(xiàn)就相當于命令模式的receiver
4.1 狀態(tài)模式
4.1.1 面臨的問題
來思考上面的實現(xiàn)茁裙,現(xiàn)在在executeGen方法里面只有兩步實現(xiàn)塘砸,可是不排除今后有更多需要調(diào)用的功能,比如:在內(nèi)容生成后執(zhí)行事件處理等等晤锥。
通常情況下掉蔬,我們還希望保持DefaultGenInvocation的通用性,該怎么辦呢矾瘾?換句話說女轿,executeGen方法里面的調(diào)用流程是可能變動的,或者是需要添加新的流程步驟壕翩,或者是需要改變調(diào)用的順序等等蛉迹。
該怎么實現(xiàn)這樣的功能呢?
4.1.2 用狀態(tài)模式來解決
允許一個對象在其內(nèi)部狀態(tài)改變時改變它的行為戈泼。對象看起來似乎修改了它的類婿禽。
4.1.3 使用狀態(tài)模式來解決問題的思路
要解決上面的問題,一個很簡單的思路就是:其實就是相當于用狀態(tài)模式來模擬調(diào)用的工作流程大猛,把調(diào)用流程的每一步單獨包裝成為一個狀態(tài)對象扭倾,然后在一個對象執(zhí)行過后,由這個狀態(tài)對象來設(shè)置下一步狀態(tài)挽绩,使得流程繼續(xù)流轉(zhuǎn)膛壹。
4.1.4 此時具體調(diào)用模塊的結(jié)構(gòu)示意如圖
4.2 模板方法
4.2.1 面臨的問題
面臨的問題在調(diào)用每個theme的action來generate內(nèi)容的時候,雖然action是由theme提供的,也就是由開發(fā)人員自行擴展的模聋,但是調(diào)用action的過程是一樣的肩民。
有些朋友會想,調(diào)用過程一樣的链方,那就做成公共的功能吧持痰,但是又發(fā)現(xiàn)其中某些步驟執(zhí)行的功能并不一樣,比如具體的action的處理是不一樣的祟蚀,這該如何處理呢工窍?
4.2.2 用模板方法模式來解決
定義一個操作中的算法的骨架,而將一些步驟延遲到子類中前酿。模板方法使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟患雏。
4.2.3 使用模板方法模式來解決問題的思路
既要約束子類的功能,又要為子類提供公共的功能罢维,很明顯應(yīng)用抽象類來做一個公共的父類淹仑。而公共功能中某些步驟執(zhí)行的功能并不一樣,那就可以把這些不一樣的功能延遲到子類來執(zhí)行肺孵,在父類中只要定義相應(yīng)的抽象方法就好了匀借。
從而把調(diào)用過程看成是算法的骨架,而調(diào)用action的處理方法悬槽,當作原語操作怀吻,只有子類才知道如何實現(xiàn)具體的generate瞬浓;而在action操作前后調(diào)用的方法初婆,并不是每個generate都需要的功能,因此可以當作鉤子方法來實現(xiàn)猿棉,也就是在父類中給出默認的實現(xiàn)磅叛,而子類根據(jù)需要來覆蓋。
4.2.4 此時具體調(diào)用模塊的結(jié)構(gòu)示意如圖
4.3 工廠方法
4.3.1 面臨的問題
面臨的問題觀察上面的實現(xiàn)萨赁,發(fā)現(xiàn)在模板方法generate里面弊琴,調(diào)用的第一步,需要得到用來封裝generate內(nèi)容的對象杖爽。
但是在父類里面敲董,它并不知道究竟要generate成為什么樣子,只有theme中的action才知道具體是什么類型慰安,也就是說父類不知道某個對象的類型腋寨,也不知道如何獲取這個對象,該怎么辦呢化焕?
4.3.2 用工廠方法模式來解決
定義一個用于創(chuàng)建對象的接口萄窜,讓子類決定實例化哪一個類,F(xiàn)actory Method使一個類的實例化延遲到其子類。
4.3.3 使用工廠方法模式來解決問題的思路
要解決上面的問題查刻,一個很簡單的思路就是:在父類里面定義一個抽象方
法键兜,返回模板方法需要的對象,把初始化對象的任務(wù)延遲到子類去穗泵。
這個方法就是一個工廠方法普气,同時也作為模板方法模式里的原語操作之一。
4.3.4 此時具體調(diào)用模塊的結(jié)構(gòu)示意如圖
4.4 裝飾器
4.4.1 面臨的問題
面臨的問題分析上面的實現(xiàn)佃延,在調(diào)用模板方法generate的過程中棋电,可能需要在具體的 Action之前執(zhí)行一定的功能,也可能需要在具體的Action之后執(zhí)行一定的功能苇侵,而且這些功能具體是什么赶盔,具體的Action方法并不知道。
也就是說榆浓,需要在Action方法不知情的情況下于未,給他添加上新的功能,可能會在action方法之前或者之后執(zhí)行一些功能陡鹃。該怎么辦呢烘浦?
4.4.2 用裝飾者模式來解決
動態(tài)地給一個對象添加一些額外的職責。就增加功能來說萍鲸,裝飾模式比生成子類更為靈活闷叉。
4.4.3 使用裝飾者模式來解決問題的思路
要解決上面的問題,一個很簡單的思路就是:定義一個公共的組件對象脊阴,作為原始對象和裝飾對象的父類握侧,然后在裝飾對象里面,采用動態(tài)組合的方式來給傳入的組件對象透明的添加新的功能
4.4.4 此時具體調(diào)用模塊的結(jié)構(gòu)示意如圖
4.5 觀察者模式
4.5.1 面臨的問題
繼續(xù)分析上面的實現(xiàn)嘿期,在加入了模板方法模式品擎、工廠方法模式和裝飾器模式過后,在DefaultGenInvocation的executeGen方法里面备徐,調(diào)用每個theme的 action來生成內(nèi)容的功能就很容易實現(xiàn)出來了萄传。
可是,把內(nèi)容輸出去的步驟應(yīng)該怎么實現(xiàn)呢蜜猾?
按照現(xiàn)在的要求秀菱,同一個generate的功能,可能會有多個輸出蹭睡,輸出形式還不一樣衍菱,那么,該怎么實現(xiàn)這個功能呢棠笑?
4.5.2 用觀察者模式來解決
定義對象間的一種一對多的依賴關(guān)系梦碗,當一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新。
4.5.3 使用觀察者模式來解決問題的思路
要解決上面的問題洪规,一個很簡單的思路就是:把生成調(diào)用當成目標對象印屁,而需要輸出的對象當成多個觀察者,這樣一來斩例,當目標對象的狀態(tài)變化的時候雄人,也就是需要輸出的內(nèi)容已經(jīng)generate過后,就可以通知這多個觀察者念赶,讓這些觀察者自行輸出內(nèi)容础钠。
4.5.4 此時具體調(diào)用模塊的結(jié)構(gòu)示意如圖
5.和其他模塊的交互實現(xiàn)
使用中介者模式