策略模式屬於Java 23種設計模式中行為模式之一,那就先看看什麼是策略模式。
策略模式的定義:
#此設計模式封裝了一系列演算法,使它們能夠相互替換,而演算法變化不會對客戶端使用造成影響。策略模式屬於物件行為模式,它透過對演算法進行封裝,把使用演算法的責任和演算法的實作分割開來,並委派給不同的物件來管理這些演算法。
其實我們在現實生活中常常遇到實現某種目標存在多種策略可供選擇的情況,例如,出行旅遊可以乘坐飛機、乘坐火車、騎自行車或自己開私家車等。 或例如網購,你可以選擇工商銀行、農業銀行、建設銀行等等,但是它們提供的演算法都是一致的,就是幫你付款。
在軟體開發中也會遇到類似的情況,當實現某一個功能存在多種演算法或策略,我們可以根據環境或條件的不同選擇不同的演算法或策略來完成該功能。
優點:
多條件語句不易維護,而使用策略模式可以避免使用多重條件語句
透過繼承,可以將演算法族的公共程式碼放在父類別中,以避免程式碼重複使用,並提供了一系列可重複使用的演算法
提供相同行為的不同實現,客戶可以根據不同時間或空間要求選擇不同的
提供了對開閉原則的完美支持,可以在不修改原程式碼的情況下,靈活增加新演算法把演算法
的使用放到環境類別中,而演算法的實作移到具體策略類別中,實作了二者的分離
缺點:
#客戶端必須理解所有策略演算法的區別,以便適時選擇適當的演算法類
策略模式造成很多的策略類,增加維護難度
1 .抽象策略類別:定義了一個公共接口,各種不同的演算法以不同的方式實現這個接口,環境角色使用這個接口調用不同的演算法,一般使用接口或抽象類實現。
2.具體策略類別:實作了抽象策略定義的接口,提供具體的演算法實作。
3.環境類別:持有一個策略類別的引用,最終給客戶端呼叫。
結構圖:
現在有三隻鴨子: 綠毛鴨、紅毛鴨、小鴨子(小鴨子還不會飛)
現在定義一隻鴨子的父類:裡面有都會叫的方法,有顯示外觀的方法(因為每隻都不一樣,就需要子類別重寫)
也會飛行 (這裡使用策略模式)
public abstract class duck { //鸭子都会叫: public void quack(){ System.out.println("嘎嘎嘎"); } //鸭子的外观,因为都不一样,所以由子类去实现 public abstract void display(); //以下使用策略模式: //在父类中持有该接口,并由该接口代替飞行行为(组合) private Flying flying; //提供set方法 public void setFlying(Flying flying) { this.flying = flying; } public void fly(){ flying.Fly(); } }
定義一個飛行介面:
/** * 策略接口:实现了鸭子的飞行行为 */ public interface Flying { void Fly(); }
我們知道策略模式就是把需要用的演算法封裝起來,就在另一個套件內封裝了會飛和不會飛的兩個方法:
會飛(繼承至上面的飛行接口,重寫飛行方法):
public class FlyWithWin implements Flying { @Override public void Fly() { System.out.println("我会飞"); } }
#不會飛:
public class FlyNoWay implements Flying { @Override public void Fly() { System.out.println("我不会飞行"); } }
注意: 上面這兩個方法我是把他們單獨封裝起來,當做演算法族,然後程式需要使用裡面某個演算法的時候,程式不會受演算法改變的影響,因為這裡面的演算法最終效果是一致的
紅毛鴨類:
/** * 红色鸭子 */ public class RedDuck extends duck{ public RedDuck(){ super(); //给鸭子注入飞行的能力,这里就是通过算法族里面的会飞的算法 super.setFlying(new FlyWithWin()); } @Override public void display() { System.out.println("我是红色的鸭子"); } }
綠毛鴨:
/** * * 绿色鸭子 */ public class GreenDuck extends duck{ public GreenDuck(){ super(); //给鸭子注入飞行的能力,这里也是通过算法族里面的会飞的算法 super.setFlying(new FlyWithWin()); } @Override public void display() { System.out.println("我是绿色的鸭子"); } }
小鴨子類別(不會飛):
/** * 小鸭子,还不会飞 */ public class SamllDuck extends duck{ public SamllDuck(){ super(); //小鸭子不会飞,所以使用了算法族里面不会飞的算法 super.setFlying(new FlyNoWay()); } @Override public void display() { System.out.println("我还是小鸭子"); } //因为小鸭子和大鸭子的叫声不一样,所以重写叫声方法 public void quack(){ System.out.println("嘎~嘎~嘎"); } }
測試類別:
public class Test { public static void main(String[] args) { System.out.println("***测试鸭子程序***"); duck d = null; //这下面是轮流运行!!!! d = new RedDuck(); //测试红色的鸭子 d = new GreenDuck(); //测试绿色的鸭子 d = new SamllDuck(); //测试小鸭子 d.display(); d.quack(); d.fly(); System.out.println("***测试完毕***"); } }
#當使用紅毛鴨為物件時:
***測試鴨子程式***
我是紅色的鴨子
嘎嘎嘎
我會飛
***測試完畢***
當使用綠毛鴨為物件時:
***测试鸭子程序*** 我是绿色的鸭子 嘎嘎嘎 我会飞 ***测试完毕***
當使用小鴨子為物件時:
***測試鴨子程式***
我還是小鴨子
嘎~嘎~嘎
我不會飛行
* **測試完畢***
1.當一個系統需要動態地在幾種演算法中選擇一種時,可將每個演算法封裝到策略類別中
2.一個類別定義了多種行為,並且這些行為在這個類別的操作中以多個條件語句的形式出現,可將每個條件分支移入它們各自的策略類別中以取代這些條件語句
3.系統中各演算法彼此完全獨立,且要求對客戶隱藏具體演算法的實作細節時
4.系統要求使用演算法的客戶不應該知道其操作的資料時,可使用策略模式來隱藏與演算法相關的資料結構
5.多個類別只區別在表現行為不同,可以使用策略模式,在執行時期動態選擇具體要執行的行為
以上是Java的策略模式用程式碼怎麼實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!