設計模式之策略模式(Strategy Pattern)

來源:互聯網
上載者:User

標籤:style   blog   http   color   java   ar   strong   2014   div   

一.什麼是策略模式(Strategy Pattern)?

從字面上理解,策略模式就是應用了某種“策略”的設計模式,而這個“策略”就是:把變化的部分封裝起來。

二.舉個例子

假定現在我們需要用類來描述Dog

首先,所有的Dog都有外形(比如Color),有行為(比如Run、Bark)

於是我們很自然地定義了這樣一個基類Dog:

public abstract class Dog {public abstract void display();//顯示Dog的外形public abstract void run();//定義Dog的Run行為}

其它的Dog具體類全部繼承自Dog基類就好了,很快,需求來了

有一隻Red Dog,它是寵物犬,跑得很慢,叫聲也很小

於是我們又定義了RedDog類:

public class RedDog {@overridepublic void display(){System.out.println("this is a red dog.");}@overridepublic void run(){System.out.println("it‘s running slowly.");}}

接著,來了一大批需求,Black Dog、Gray Dog、Pink Dog、BlackGrayDog、PinkGrayDog。。。一共100隻Dog,除Color不同外,Run的速度也不同

於是我們定義了100個類來表示100種不同類型的Dog,每個類中都實現了Run方法與Display方法。

嗯~,看看我們的類圖,沒錯,這個BigBang就是我們的類圖了,好像很合理啊,有100種Dog當然會有100個類啊,而且具體Dog類當然要繼承自Dog基類吧?嗯,好像是這樣的,而且這樣好像也沒什麼不好,至少現在看不出來有什麼不妥。。。

-------

又一個新的需求來了,我們發現Dog不僅可以Run,還可以Bark

自然而然地,我們想到了給Dog基類定義一個新行為Bark,然後在100個具體類中逐一重寫了Bark方法。。。

雖然過程有些麻煩,不過好在我們還是解決了問題,現在所有的Dog都可以Bark了

-------

這天,來了一隻新Dog,它叫ToyDog,是玩具狗,不會Run也不能Bark,只是個玩偶

於是我們讓ToyDog繼承了Dog基類,重寫了Run方法和Bark方法(方法體為空白,因為Toy不會Run也不會Bark)

問題好像也被完美解決了,至少現在看來不存在什麼問題

-------

很多天后,ToyDog工廠技術革新了,新產品被裝上了電池,可以Bark了

沒關係,我們修改了ToyDog類,實現了Bark

-------

我們初始化了一隻ToyDog,它歡快的BarkBarkBark,過了一會兒,電池沒電了,ToyDog不能Bark了,但是我們的ToyDog類顯示它還可以Bark。。。

*******

現在,終於出問題了吧,我們發現Dog問題中最難處理的部分就是Run、Bark這兩個行為,一旦發生變化我們就需要修改具體Dog類,甚至是Dog基類,不僅需要花費大量的時間,而且所有具體Dog類中都實現了Run與Bark方法,顯得很臃腫。還有最重要的問題,我們無法動態地修改Dog的行為,比如小Dog跑得慢叫聲小,長大後跑得快叫聲大,也無法應對上面提到的電池沒電導致的行為變化問題。。。。這一系列的問題想向我們說明一點:這從一開始就是一個糟糕的設計。

三.如何應用策略模式?

策略模式要求把變化的部分封裝起來,首先,我們要找到代碼中頻頻發生變化的部分

在上一個例子中,變化的部分是什嗎?

1.Run行為

2.Bark行為

3.其它可能存在的行為

...

下面我們把這些行為封裝起來(以Run為例):

package StrategyPattern;/** * @author ayqy * 定義Run介面 * */public interface IRun {public void run();//定義run行為}
package StrategyPattern;/** * @author ayqy * 實現RunQuickly行為 * */public class RunQuickly implements IRun{@Overridepublic void run() {System.out.println("it‘s running quicky.");}}
package StrategyPattern;/** * @author ayqy * 實現RunSlowly行為 * */public class RunSlowly implements IRun{@Overridepublic void run() {System.out.println("it‘s running slowly.");}}
package StrategyPattern;/** * @author ayqy * 實現RunNoWay行為 * */public class RunNoWay implements IRun{@Overridepublic void run() {System.out.println("it isn‘t able to run.");}}

Bark行為的封裝與之類似

封裝好“變化”之後,我們的Dog基類也要做相應改變:

package StrategyPattern;/** * @author ayqy * 定義Dog基類 * */public abstract class Dog {IBark bark;IRun run;public abstract void display();//顯示Dog的外形public IBark getBark() {return bark;}public void setBark(IBark bark) {this.bark = bark;}public IRun getRun() {return run;}public void setRun(IRun run) {this.run = run;}}

注意,我們只封裝了容易發生變化的部分(Bark與Run),而沒有封裝Display方法(Dog的外形應該比較fixed吧),什麼才是“變化的部分”?這需要我們仔細考慮,視具體情景而定

現在來看看我們新的具體Dog類吧

package StrategyPattern;/** * @author ayqy * 實現RedDog * */public class RedDog extends Dog{public RedDog(){//紅狗是寵物狗//跑得慢,叫聲小super.setRun(new RunSlowly());super.setBark(new BarkQuietly());}@Overridepublic void display() {System.out.println("this is a red dog.");}}

類被明顯瘦身了吧,而且我們現在還能在運行時動態地修改Dog的行為,看到策略模式的威力了吧。

三.效果樣本

編寫一個測試類別:

package StrategyPattern;/** * @author ayqy * 測試策略模式<br/> * 策略模式,簡單的說就是要求把“變化”封裝起來,以隔離“變化”對其它部分的影響 * */public class Test {/** * @param args */public static void main(String[] args) {System.out.println("------- 創造一隻Red Dog -------");Dog redDog = new RedDog();showDogInfo(redDog);System.out.println("\n------- 創造一隻Black Dog -------");Dog blackDog = new BlackDog();showDogInfo(blackDog);System.out.println("\n------- 創造一隻Toy Dog -------");Dog toyDog = new ToyDog();showDogInfo(toyDog);System.out.println("\n------- 技術革新,現在Toy Dog可以小聲叫了 -------");toyDog.setBark(new BarkQuietly());showDogInfo(toyDog);//上面的代碼並不是最優的,只是為了說明策略模式//一個很明顯的問題是Dog redDog = new RedDog();//我們在面向具體對象編碼,而不是設計模式所提倡的面向介面編碼//可以定義一個Dog工廠來生產Dog對象以求模組之間更松的耦合}/** * @param dog * 顯示Dog相關資訊 */private static void showDogInfo(Dog dog){dog.display();dog.run.run();dog.bark.bark();}}

運行結果樣本:

四.總結

策略模式的核心是要把頻繁發生變化的部分封裝起來,作用是把變化部分的影響隔離開,避免局部的變化對其它fixed部分造成影響,設計時可能需要更多的時間,但便於維護、複用與擴充,在本例中,Run、Bark行為都可以在新的類(如Pig)中複用;一旦行為發生變化我們只需要修改各個行為介面,最多再對Dog基類做簡單修改就可以從容地應對變化了。

設計模式之策略模式(Strategy Pattern)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.