Java 设计模式之策略模式
一、了解策略模式
1.1 什么是策略模式
策略模式 (Strategy Pattern) 是指對一系列的算法定義,并將每一個算法封裝起來,而且使它們還可以相互替換。此模式讓算法的變化獨立于使用算法的客戶。
1.2 策略模式組成結構
- 環境 (Context):持有一個策略類的引用,最終給客戶端調用。
- 抽象策略 (Strategy): 策略類,通常是一個接口或者抽象類。
- 具體策略 (ConcreteStrategy):實現了策略類中的策略方法,封裝相關的算法和行為。
1.3 策略模式 UML 圖解
1.4 策略模式應用場景
- 多個類只區別在表現行為不同,可以使用 Strategy 模式,在運行時動態選擇具體要執行的行為。
- 需要在不同情況下使用不同的策略 (算法),或者策略還可能在未來用其它方式來實現。
- 對客戶隱藏具體策略 (算法) 的實現細節,彼此完全獨立。
二、策略模式具體應用
2.1 問題描述
模擬鴨子游戲:游戲中會出現各種鴨子,一邊游泳戲水、一邊呱呱叫,為了提高游戲的樂趣,加入了讓鴨子飛的功能。但是考慮到并不是所有的鴨子都會飛,比如下面這種橡皮鴨。現在讓你利用 OO 技術,設計鴨子相關的類。
2.2 使用繼承
我們可能想到使用繼承,在超類 Duck 中定義鴨子的相關方法,并實現其對應的動作,這樣就能讓所有鴨子都可以對應其 fly() 的動作。在定義橡皮鴨時,只需要覆蓋其父類 (Duck) 中的 fly() 方法即可。
如果我們還想加入誘餌鴨,這種鴨子既不會叫,也不會飛,那么我們就要繼承 Duck 類,重寫其中的 quack() 、display() 和 fly() 方法。
這種通過繼承的方法是可以解決問題,但是有很多的局限
- 代碼在多個子類中重復。
- 運行時的行為不容易改變。
- 很難知道鴨子的全部行為。
- 改變會牽一發動全身,造成其他鴨子不想要的改變。
2.3 使用接口
認識到上面繼承的不足,我們可能想到了另一種方式去解決這種問題,通過接口的方式去實現某些動作。把 fly() 和 quack() 方法從 Duck 類中抽取抽取出來,分別放在 Flyable 和 Quackable 接口中。
通過接口的方式是可以完成任務,但是這也確實是一個很笨的方式。因為對于很多種鴨子來說,它們大部分都會飛與呱呱叫,但是我們在定義它們類的時候都要去實現 Flyable 和 Quackable 接口,這樣一來重復的代碼更多了。
2.4 問題歸零
到這里我們知道使用繼承并不能很好的解決問題,因為鴨子的行為在子類中是不斷變化的,并且讓所有的鴨子都具有這些行為是不恰當的,比如橡皮鴨不具有飛的行為。通過接口的方式似乎還不錯,但是 Java 接口并不具備實現代碼,所以繼承接口并不能達到代碼復用的目的,一不小心,就可能造成新的錯誤!
幸運的是,有一個設計原則,恰好適用于這種狀況:找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起。這樣以來,代碼變化引起的后果變少,系統將更有彈性。
2.5 策略模式登場
除了 fly() 和 quack() 方法之外,Duck 中的其他方法還算一切正常,沒有什么需要經常需要變化或修改的地方。所以除了 fly() 和 quack() 方法,我們不打算對 Duck 中的其他方法做太多處理。我們希望一切具有彈性,正是因為沒有彈性,上面兩種方法都被我們淘汰掉了。
比如說,我們要產生一個綠頭鴨的實例,并制定特定“類型”的飛行行為給它。我們可以在鴨子類中包含設定行為的方法,這樣就可以在“運行時”動態地“改變”綠頭鴨的飛行行為。
有了這些實現目標,于是就有了第二個設計原則:針對接口編程,而不是針對實現編程。
這里我們使用接口代表每個行為,比如說,FlyBehavior 與 QuackBehavior,而行為的每個實現都將實現其中一個接口。所以這次鴨子類不會去實現 Flyable 和 Quackable 接口,反而是由我們制造一組其他類專門實現 FlyBehavior 與 QuackBehavior,這就稱為“行為”類。由行為類而不是 Duck 類來實現該接口。
(1)策略模式設計圖
改造原來的鴨子類
(2) 代碼實現
這里我們將 Duck 類定義成抽象類,并把 display() 方法定義成抽象方法。
接口 QuackBehavior
package com.jas.strategy;public interface QuackBehavior {void quack(); }接口 QuackBehavior 實現類 Quack(實現鴨子呱呱叫)
package com.jas.strategy;public class Quack implements QuackBehavior {@Overridepublic void quack() {System.out.println("Quack!");} }接口 QuackBehavior 實現類 SQuack(實現鴨子橡皮吱吱叫)
package com.jas.strategy;public class SQuack implements QuackBehavior {@Overridepublic void quack() {System.out.println("SQuack!");} }接口 QuackBehavior 實現類 MuteQuack(實現鴨子不會叫)
package com.jas.strategy;public class MuteQuack implements QuackBehavior {@Overridepublic void quack() {System.out.println("Silence!");} }接口 FlyBehavior
package com.jas.strategy;public interface FlyBehavior {void fly(); }接口 FlyBehavior 實現類 FlyWithWings(實現鴨子飛)
package com.jas.strategy;public class FlyWithWings implements FlyBehavior {@Overridepublic void fly() {System.out.println("I'm flying!");} }接口 FlyBehavior 實現類 FlyNoWay(實現鴨子不會飛)
package com.jas.strategy;public class FlyNoWay implements FlyBehavior {@Overridepublic void fly() {System.out.println("I can't fly!");} }Duck 類
package com.jas.strategy;public abstract class Duck {private QuackBehavior quackBehavior;private FlyBehavior flyBehavior;public void swim(){System.out.println("All ducks float.");}public abstract void display();public void performQuack(){quackBehavior.quack();}public void performFly(){flyBehavior.fly();}public void setQuackBehavior(QuackBehavior quackBehavior){this.quackBehavior = quackBehavior;}public void setFlyBehavior(FlyBehavior flyBehavior){this.flyBehavior = flyBehavior;}}測試類 RubberDuck
package com.jas.strategy;public class RubberDuck extends Duck {@Overridepublic void display() {System.out.println("Rubber Duck");}public static void main(String[] args) {Duck rubberDuck = new RubberDuck(); //橡皮鴨實例rubberDuck.setQuackBehavior(new SQuack()); //橡皮鴨吱吱叫rubberDuck.setFlyBehavior(new FlyNoWay()); //橡皮鴨不會飛rubberDuck.performQuack();rubberDuck.performFly();} }//輸出 //SQuack! //I can't fly!2.6 從策略模式組成結構對問題進行總結
三、策略模式總結
3.1 策略模式的優缺點
優點
1、 策略模式提供了管理相關的算法族的辦法,從而避免重復的代碼。
2、 策略模式提供了可以替換繼承關系的辦法。因為繼承使得動態改變算法或行為變得不可能。
3、 使用策略模式可以避免使用多重條件轉移語句。
缺點
1、客戶端必須知道所有的策略類,并自行決定使用哪一個策略類。
2、 策略模式造成很多的策略類,每個具體策略類都會產生一個新類。
PS:點擊了解更多設計模式 http://blog.csdn.net/codejas/article/details/79236013
四、參考文獻
《Head First 設計模式》
總結
以上是生活随笔為你收集整理的Java 设计模式之策略模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 鹤岗市7月份烟草情况?7月份烟草
- 下一篇: 抽烟会使密闭的室内pm2.5值急剧升高,