民初思韻網

加入收藏   設為首頁
選擇語言   簡體中文
你好,請 登陸 或 注冊
首頁 人文思韻 傳奇人物 歷史思潮 時代作品 話題討論 國民思韻 民初捐助 賬戶管理
  搜索  
    人文精神 >>> 技術的天空 溫和的思緒
字體    

C#面向對象設計模式縱橫談 第23講:Strategy 策略模式
C#面向對象設計模式縱橫談 第23講:Strategy 策略模式
MSDN 網絡廣播 李建忠     阅读简体中文版

2006.9.25 李建忠

算法與對象的耦合

對象可能經常需要使用多種不同的算法,但是如果變化頻繁,會將類型變得脆弱……

image

 

動機(Motivation)

在軟件構建過程中,某些對象使用的算法可能多種多樣,經常改變,如果將這些算法都編碼到對象中,將會使對象變得異常復雜;而且有時候支持不使用的算法也是一個性能負担。

如何在運行時根據需要透明地更改對象的算法?將算法與對象本身解耦,從而避免上述問題?

 

意圖(Intent)

定義一系列算法,把它們一個個封裝起來,并且使它們可互相替換。該模式使得算法可獨立于使用它的客戶而變化。

——《設計模式》GoF

 

例說Strategy模式應用

image

這個程序有兩個可能的變化點:當枚舉類型增加時,即處理的方法增加,那么Process函數需要修改補充一個if else分支;當我們想對分支1的處理ProcessA進行更改時,也要對Process函數進行修改。

針對上面的問題,我們首先想到的是把ProcessA寫成受保護的虛函數(在OO中我們一般把虛函數都寫成受保護的函數,因為它是能改變類的行為的函數,一般情況下只應該作為子類和父類之間的協議出現)。

Strategy模式的設計

image

把Cart類和ProcessStrategy類作為對象組合的方式使用。IProcessStrategy表達的是一個算法抽象。

抽象和具體算法

image

客戶程序

image

這樣算法就可以動態地去改變了,我們動態地去new一組具體的Process算法,然后提供給Cart類使用。

delegate只要符合參數和返回值,不管是靜態方法或者是抽象方法,就可以動態地掛上。但是接口需要抽象含義一致,因此對于這個模式更推薦使用接口來表達抽象的算法。

 

結構(Structure)

image

算法并不是孤立的,它通常都需要有一些上下文去調用它,或者是傳入一些參數。Strategy類型里面不攜帶狀態信息(這是與模板方法的區別,模板方法本身是攜帶狀態信息的),我們不能把它看成一種實例,即使有狀態,也是會通過參數傳入。一個Strategy定義了一個算法的完整步驟和結構,只要用一個Strategy具體類,就可以完成整個算法的操作,不會有其它依賴和耦合。Context和Strategy是一個對象組合的使用關系。Strategy中的抽象接口隨時可以替換成具體的類,達到在不同算法之間動態地切換。

這個模式的核心是通過對象組合的方式把本來直接調用的內容委托給接口實體對象來完成,至于接口實體對象具體是什么,在運行時才知道,即是運行時改變。

 

Strategy模式的幾個要點

Strategy及其子類為組件提供了一系列可重用的算法,從而可以使得類型在運行時方便地根據需要在各個算法之間進行切換,所謂封裝算法,支持算法的變化。

Strategy模式提供了用條件判斷語句以外的另一種選擇,消除條件判斷語句,就是在解耦合。含有許多條件判斷語句的代碼通常都需要Strategy模式。

與State類似,如果Strategy對象沒有實例變量,那么各個上下文可以共享一個Strategy對象,從而節省對象開銷。

Strategy模式適用的是算法結構中整個算法的改變,而不是算法中某個部分的改變。

 

Template Method方法:執行算法的步驟協議是本身放在抽象類里面的,允許一個通用的算法操作多個可能實現

Strategy模式:執行算法的協議是在具體類,每個具體實現有不同通用算法來做。

 

.NET框架中的Strategy應用

image

例如ArrayList類,Sort方法做不了什么事情,因為Point類不支持排序,沒有繼承IComparer接口。

image

但如果我們想支持排序,其實Sort方法就是一個Strategy模式,它支持傳入一個繼承IComparer接口的具體類。

image

IComparer接口其實就是Strategy我們上面例子中的IProcessStrategy。我們可以實現一個IComparer接口,然后把具體類傳入,這樣Sort方法就會按我們定義的排序規則執行了。

image

當我們需要切換排序方法的時候,只需要更改傳入Sort的具體比較類即可。

image

ArrayList雖然沒有把排序方法作為字段組合,但是它把它作為參數來使用了。因為比較不是在ArrayList中大多數方法都使用,只有排序才需要使用,所以把它作為參數使用更合適。

2010.10.28

2013-08-22 08:53

歡迎訂閱我們的微信公眾賬號!
春秋茶館訂閱號
微信號 season-tea(春秋茶館)
每天分享一篇科技/遊戲/人文類的資訊,點綴生活,啟迪思想,探討古典韻味。
  清末民初歷史人物  民初人物
孫中山的啟蒙者
近現代的嶺南,湧現出大批引領中國前行的先驅者,近代改良主義者,香港華人領袖何啟便是其中的一位。他不僅是孫中山在香港西醫書院的老師,更是孫中山走向革命道路的思想導師。
為傳統文化招魂
錢穆(1895年7月30日-1990年8月30日),原名恩,字賓四,江蘇無錫人,歷史學家,儒學學者,教育家。錢穆對中國古代政治制度有良好觀感,認為中國傳統政治非但不是君主....
資助民初精神網
        回頂部     寫評論

 
評論集
暫無評論!
發表評論歡迎你的評論
昵稱:     登陸  註冊
主頁:  
郵箱:  (僅管理員可見)

驗證:   验证码(不區分大小寫)  
© 2011   民初思韻網-清末民初傳奇時代的發現與復興   版權所有   加入收藏    設為首頁    聯繫我們    1616導航