設計模式之策略模式

 策略模式的理解

  • 最初的設計

假設有一家公司——帕特蘭,該公司研製了一款生產設備,可以生產出多功能高科技產品uranus G1(第一代)。G1產品具有AB兩項功能,深受全球用戶喜愛,掀起一股搶購浪潮,產品開始大規模銷往世界各地,中國、意大利、法國、德國等很多國家。

但是很快,各國用戶開始反映,雖然AB功能非常實用,但產品外觀有些單一,銷往各國的產品長得都一樣,如果每款產品可以體現各國自己的風情文化,豈不更好?

帕特蘭公司立刻採取行動,針對各國風情設計了不同的外觀,如銷往中國的加入了中國風,銷往法國的則加入了浪漫的元素。於是,生產線現在是這樣:

wKiom1Ohp6HDSWcpAACS6KjjdtE731.jpg


圖1

  • 加入新的功能

隨着用戶的需求不斷增加,帕特蘭公司決定給G1系列產品加入功能C。因爲生產線採用了OO的思想,只需要在基類中加入功能C(如圖2所示),那麼所有繼承該基類的子類(即圖1中標號爲234的分支線)生產出的G1產品,自然就具有了功能C,設計者們這下嚐到了OO設計與繼承的甜頭。


wKioL1Ohp4bCjrTAAABxU7pGRg0930.jpg

圖2

  • 產品又升級

現在又需要加入D功能。帕特蘭公司在這方面已經駕輕就熟,只需要像加入C功能一樣在基類中加入D就好了,而且產品開始銷往更多的國家。

wKiom1Ohp9OD56FAAACLXQGkunQ400.jpg

圖3

可是這次沒有像之前那麼順利,由於各國地區文化差異,法國和美國某些地區的用戶,美國加州的用戶不喜歡D功能,法國巴黎的用戶覺得D功能稍微修改一下,變成D1功能比較合口味。帕特蘭公司的設計者採用了這樣的方式解決這個問題:生產線再加入一級過濾層,

對個別地區的產品進行修整,其餘大部分產品保持原樣即可。


wKiom1OhqBCzSQR_AACzqRnIpp8395.jpg

圖4

雖然解決了這個問題,但是帕特蘭公司的設計者開始發現設計中存在一個非常大的問題,那就是以後還會加入E功能,還會銷往更多的國家和地區,如果E功能在更多地區出現D的類似情況,可就不妙了,比如,日本東京的用戶覺得E改成E1,而中國杭州的用戶偏偏喜歡E,意大利羅馬的用戶覺得改成E2更舒服。你想象一下,隨着功能的不斷加入,銷售地區更多,地區文化差異大,在圖中的2級分支處,讓一個人來維護,那工作量將是多麼的驚人!

  • 策略模式怎麼做

帕特蘭公司的設計人員開始研究策略模式,發現原來有一種更好的設計方式,可以將剛纔那個噩夢般的維護工作瞬間變得容易了。

設計人員做了以下幾件事情:

  1. 將世界通用的功能ABC保留在基類中實現,因爲這些功能滿足所有地區,幾乎不會變動;

  2. 將容易隨着地區不同而變動的DE功能的實現從基類中抽離出來,只留了兩個位置de,表示這兩個功能,主生產線暫時不實現;

  3. 對位置de規定了接口規範,比如d位置有三個菱形插孔,e位置有兩個圓形插孔,採用該接口規範設計的零件可以安插在相應的位置,即插即用

  4. 成立一條獨立的生產線line2(原來的生產線統稱爲line1),專門負責生產實現DD1、空DEE1、空E等功能的零件,並採用3中規定的接口標準。

  5. 安排一個人peter,專門負責從line1中取出G1半成品(即只有ABC功能,DE只留了位置),從line2取出生產出的DE零件,將零件安插在相應的位置上;

現在情況是什麼呢?

  1. 以後再有哪個地區突然說不喜歡DE,或者要改成D2E2,亦或是D3E3也沒關係,只需要在line2中添加一個這樣的零件,而line1仍舊像以前一樣保留de位置,一點修改都不用做,在打算生產具有D2E2D3E3功能的產品時,peter自然會取出新添加的零件,安插在預留的位置,對於peter而言,拿的動作和安插的動作也是完全相同,只是拿了不同的零件而已。

這就是策略模式。

  • 再來看概念

現在來看一下策略模式的抽象概念,如果你看懂了前面的例子,那麼請原諒我到這裏才介紹概念。

策略模式的概念:將一系列行爲(動作、算法)封裝起來,功能類似的行爲都實現一個統一的接口,使這些行爲的變化修改獨立於行爲的使用者。

這裏的行爲對應的就是line2生產的具有功能D2D3E2E3的零件;

統一的接口就是預留的位置de所規定的一系列特徵,如三插孔、菱形等;

行爲的使用者即line1生產出的半成品;

預留位置,其實就是在基類中加入一個行爲對象,以接口類型來引用(即使用組合,針對接口編程),委託給變量來實現具體功能;

安插零件的動作則對應基類的set方法,來設置實際的行爲對象;

Peter扮演的就是基類和行爲類的用戶(可以理解成寫main函數的程序員),針對不同的地區調用set方法設置不同的行爲對象。

  • 設計原則

  1. 多用組合少用繼承

  2. 針對接口編程,而非針對實現編程

  3. 分離並封裝易於變化的行爲,獨立於固定不變的部分

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章