源碼地址:https://github.com/weilanhanf/PythonDesignPatterns
說明:
策略指的就是為了達到某一目的而采取的手段或者方法。為了實現軟件設計咪表,對象可能會用到多種多樣的算法。這些算法甚至會經常改變。如果將這些算法都硬編碼到對象中,將會使得對象本身變得臃腫不堪,而且有時候支持不同的算法也是一個性能負擔。策略模式很好的實現了在運行時根據需要透明的更改對象的算法和將算法與本身對象解耦,從而避免出現上述兩個問題。
因此策略模式可以定義為: 定義一系列算法,將每一個算法封裝起來,並讓它們可以相互替換。策略模式讓算法可以獨立於使用它的客戶變化。每一個封裝算法的類稱之為策略(Strategy)類,策略模式提供了一種可插入式(Pluggable)算法的實現方案
策略模式的結構
策略模式包含以下3個角色: Context(環境類) Strategy(抽象策略類) ConcreteStrategy(具體策略類)
實例:
假設某司維護着一些客戶資料,需要在該司有新產品上市或者舉行新活動時通知客戶。現通知客戶的方式有兩種:短信通知、郵件通知。應如何設計該系統的客戶通知部分?為解決該問題,我們先構造客戶類,包括客戶常用的聯系方式和基本信息,同時也包括要發送的內容。
class customer: customer_name="" snd_way="" info="" phone="" email="" def setPhone(self,phone): self.phone=phone def setEmail(self,mail): self.email=mail def getPhone(self): return self.phone def getEmail(self): return self.email def setInfo(self,info): self.info=info def setName(self,name): self.customer_name=name def setBrdWay(self,snd_way): self.snd_way=snd_way def sndMsg(self): self.snd_way.send(self.info)
#snd_way向客戶發送信息的方式,該方式置為可設,即可根據業務來進行策略的選擇。
#發送方式構建如下: class msgSender: dst_code="" def setCode(self,code): self.dst_code=code def send(self,info): pass class emailSender(msgSender): def send(self,info): print("EMAIL_ADDRESS:%s EMAIL:%s"%(self.dst_code,info)) class textSender(msgSender): def send(self,info): print("TEXT_CODE:%s EMAIL:%s"%(self.dst_code,info))
#業務場景中將發送方式作為策略 if __name__=="__main__": customer_x=customer() customer_x.setName("CUSTOMER_X") customer_x.setPhone("10023456789") customer_x.setEmail("customer_x@xmail.com") customer_x.setInfo("Welcome to our new party!") text_sender=textSender() text_sender.setCode(customer_x.getPhone()) customer_x.setBrdWay(text_sender) customer_x.sndMsg() mail_sender=emailSender() mail_sender.setCode(customer_x.getEmail()) customer_x.setBrdWay(mail_sender) customer_x.sndMsg()
打印結果
TEXT_CODE:10023456789 EMAIL:Welcome to our new party!
EMAIL_ADDRESS:customer_x@xmail.com EMAIL:Welcome to our new party!
模式優點
提供了對開閉原則的完美支持,用戶可以在不修改原有系統的基礎上選擇算法或行為,也可以靈活地增加新的算法或行為 提供了管理相關的算法族的辦法 提供了一種可以替換繼承關系的辦法 可以避免多重條件選擇語句 提供了一種算法的復用機制,不同的環境類可以方便地復用策略類
模式缺點
客戶端必須知道所有的策略類,並自行決定使用哪一個策略類 將造成系統產生很多具體策略類 無法同時在客戶端使用多個策略類
模式適用環境
一個系統需要動態地在幾種算法中選擇一種 避免使用難以維護的多重條件選擇語句 不希望客戶端知道復雜的、與算法相關的數據結構,提高算法的保密性與安全性
另外:
仔細比較一下橋接模式和策略模式,如果把策略模式的Context設計成抽象類和實現類的方式,那么策略模式和橋接模式就可以划等號了。從類圖看上去,橋接模式比策略模式多了對一種角色(抽象角色)的抽象。二者結構的高度同構,也只能讓我們從使用意圖上去區分兩種模式:橋接模式解決抽象角色和實現角色都可以擴展的問題;而策略模式解決算法切換和擴展的問題。