天天看點

[Head First設計模式]政策模式

<a href="http://www.cnblogs.com/wolf-sun/p/3468100.html">[head first設計模式]山西面館中的設計模式——裝飾者模式</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3473744.html">[head first設計模式]山西面館中的設計模式——觀察者模式</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3475061.html">[head first設計模式]山西面館中的設計模式——建造者模式</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3485805.html">[head first設計模式]餃子館(冬至)中的設計模式——工廠模式</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3489549.html">[head first設計模式]一個人的平安夜——單例模式</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3514935.html">[head first設計模式]搶票中的設計模式——代理模式</a>

該過年了,總讓人有點浮躁,公司就省倆人了,唉,如果坐等時間,那實在難熬,隻能給自己找點事做,轉移一下注意力。進入今天的主題吧政策模式。

政策模式定義了算法族,分别封裝起來,讓它們之間可以互相替換,此模式讓算法的變化獨立于使用算法的客戶。

模拟鴨子的簡單應用

joe上班的公司做了一套相當成功的模拟鴨子遊戲simuduck,遊戲中出現各種鴨子,一邊遊戲戲水,一邊呱呱叫。此系統的内部設計使用了标準的oo技術,設計了一個鴨子超類,并讓各種鴨子繼承此超類。

[Head First設計模式]政策模式

讓鴨子能飛

去年,公司的競争力加劇,公司主管認為該是創新的時候了。主管認為,此模拟程式需要會飛的鴨子,将競争者抛在後面。

[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式

 改進繼承

joe認識到繼承可能不是一個好的解決辦法,因為他剛剛拿到來自主管的備忘錄,希望以後每六個月更新産品(至于更新辦法,他們還沒想到)。joe知道規格會常常改變,每當有新的鴨子子類出現,他就要被迫檢視并可能需要覆寫fly()和quack().....這簡直是無窮盡的噩夢。是以,他需要一個更清晰的方法,讓某些(而不是全部)鴨子類型可飛或可叫。

[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式

其實,并非所有的鴨子子類都具有飛行和呱呱叫的行為,是以繼承并不是适當的解決方式。雖然flyable與quackable可以解決一部分的問題(不會再有會飛的橡皮鴨),但是卻造成代碼無法複用,這隻能算是從一個噩夢跳進另一個噩夢。甚至,在會飛的鴨子中,飛行的動作可能還有多種變化......

現在我們知道使用繼承有一些缺失,因為改變鴨子的行為會影響所有種類的鴨子,而這并不恰當。flyable與quackable接口一開始似乎還挺不錯,解決了問題(隻有會飛的鴨子才繼承flyable),但是接口不具有實作代碼,是以繼承接口無法達到代碼的複用。這意味着:無論何時你需要修改某個行為,你被迫得往下追蹤并修改每一個有定義此行為的類,一不小心,可能造成新的錯誤。

設計原則:找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起。這個概念很簡單,幾乎是每個設計模式背後的精神所在,所有的模式都提供了一套方法讓系統中的某部分改變不會影響其它部分。

分開變化和不變化的部分

為了要分開變化和不變化的部分,我們準備建立兩組類,一個是fly相關,一個是quack相關的,每一組類将實作各自的動作。比如說,我們可能有一個類實作“呱呱叫”,另一個類實作“叽叽叫”,另一個類實作“安靜”。

[Head First設計模式]政策模式

設計鴨子行為

我們利用接口代表每個行為,比方說,iflybehavior與iquackbehaivor,而行為的每個實作都必須實作這些接口之一。是以這次鴨子類不會負責實作fly與quack接口,而是由其他類專門實作iflybehavior與iquackbehaivor,這就稱為“行為類”。由行為類實作行為接口,而不是由duck類實作接口。

[Head First設計模式]政策模式

 這樣的做法迥異于以往,以前的做法是:行為是繼承自duck超類的具體實作而來,或是繼承某個接口并由子類自行實作而來。這兩種做法都是依賴于實作,我們被實作綁的死死,沒辦法更改行為(除非寫更多的代碼)。

針對接口程式設計,而不是針對實作程式設計。

關于接口程式設計和實作程式設計:

假設有一個抽象類animal,有兩個具體的實作(dog與cat)繼承自animal。

[Head First設計模式]政策模式

針對實作程式設計的作法如下:

針對接口/超類型程式設計作法如下:

子類型執行個體化的動作是“在運作時才指定具體實作的對象”

實作鴨子的行為

[Head First設計模式]政策模式

這樣的設計,可以讓飛行和呱呱叫的動作被其他的對象複用,因為這些行為已經與鴨子無關了。而我們可以新增一些行為,不會影響到既有的行為類,也不會影響有使用到飛行行為的鴨子類。

內建鴨子的行為

鴨子現在會将飛行和呱呱叫的動作,委托(delegate)别人處理,而不是使用定義在自己類(或子類)内的方法。

① 首先,在鴨子中加入兩個執行個體變量, 分别為flybehavior與quackbehavior,聲明為接口類型(而不是具體類實作類型),每個變量會利用多态的方式在運作時引用正确的行為類型(例如:flywithwings、squeak . . . 等)。

我們也必須将duck類與其所有子類中的fly() 與quack( ) 移除,因為這些行為已經被搬移到flybehavior與quackbehavior類中了。我們用performfly()和performquack()取代duck類中的fly()與quack()。

[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式
[Head First設計模式]政策模式

結果

[Head First設計模式]政策模式

所有鴨子從duck繼承,飛行行為實作flybehavior接口,呱呱叫行為實作quackbehavior接口。

[Head First設計模式]政策模式

“有一個”(has a)可能比“是一個”(is a)更好

有一個關系相當有趣:每一鴨子都有一個flybehavior且有一個quackbehavior,讓鴨子将飛行和呱呱叫委托它們代為處理。

如果将兩個類結合起來使用(如同本例),這就是組合(composition)。這種作法和繼承不同的地方在于:鴨子的行為不是繼承而來,而是和适當的行為對象組合而來。

第三個設計原則

多用組合,少用繼承

使用組合建立系統具有很大的彈性,不僅可将算法族封裝成類,更可以在運作時動态地改變行為。

優缺點

優點:

1、 政策模式提供了管理相關的算法族的辦法。政策類的等級結構定義了一個算法或行為族。恰當使用繼承可以把公共的代碼轉移到父類裡面,進而避免重複的代碼。

2、 政策模式提供了可以替換繼承關系的辦法。繼承可以處理多種算法或行為。如果不是用政策模式,那麼使用算法或行為的環境類就可能會有一些子類,每一個子類提供一個不同的算法或行為。但是,這樣一來算法或行為的使用者就和算法或行為本身混在一起。決定使用哪一種算法或采取哪一種行為的邏輯就和算法或行為的邏輯混合在一起,進而不可能再獨立演化。繼承使得動态改變算法或行為變得不可能。

3、 使用政策模式可以避免使用多重條件轉移語句。多重轉移語句不易維護,它把采取哪一種算法或采取哪一種行為的邏輯與算法或行為的邏輯混合在一起,統統列在一個多重轉移語句裡面,比使用繼承的辦法還要原始和落後。

缺點:

1、用戶端必須知道所有的政策類,并自行決定使用哪一個政策類。這就意味着用戶端必須了解這些算法的差別,以便适時選擇恰當的算法類。換言之,政策模式隻适用于用戶端知道所有的算法或行為的情況。

2、 政策模式造成很多的政策類,每個具體政策類都會産生一個新類。有時候可以通過把依賴于環境的狀态儲存到用戶端裡面,而将政策類設計成可共享的,這樣政策類執行個體可以被不同用戶端使用。換言之,可以使用享元模式來減少對象的數量。

參考書

head first 設計模式

沒想到該回家了,還能耐住性子看書,這裡将書上的例子整理了一下,比較好了解。

部落格位址:

<a href="http://www.cnblogs.com/wolf-sun">http://www.cnblogs.com/wolf-sun/</a>

部落格版權:

本文以學習、研究和分享為主,歡迎轉載,但必須在文章頁面明顯位置給出原文連接配接。

如果文中有不妥或者錯誤的地方還望高手的你指出,以免誤人子弟。如果覺得本文對你有所幫助不如【推薦】一下!如果你有更好的建議,不如留言一起讨論,共同進步!

再次感謝您耐心的讀完本篇文章。

轉載:http://www.cnblogs.com/wolf-sun/p/3534573.html

繼續閱讀