策略模式定義了一系列的算法,并將每一個算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨立于使用它的客戶而獨立變化。
適用范圍:
• 許多相關的類僅僅是行為有異。 “策略”提供了一種用多個行為中的一個行為來配置一個類的方法。即一個系統需要動態地在幾種算法中選擇一種。• 需要使用一個算法的不同變體。例如,你可能會定義一些反映不同的空間 /時間權衡的算法。當這些變體實現為一個算法的類層次時 ,可以使用策略模式。• 算法使用客戶不應該知道的數據。可使用策略模式以避免暴露復雜的、與算法相關的數據結構。• 一個類定義了多種行為 , 并且這些行為在這個類的操作中以多個條件語句的形式出現。將相關的條件分支移入它們各自的Strategy類中以代替這些條件語句。
下面通過一個簡單的案列講解
例:
劉備要到江東娶老婆了,走之前諸葛亮給趙云(伴郎)三個錦囊妙計,說是按天機拆開解決棘手問題,嘿,還別說,真是解決了大問題,搞到最后是周瑜陪了夫人又折兵呀,那咱們先看看這個場景是什么樣子的。先說這個場景中的要素:三個妙計,一個錦囊,一個趙云,妙計是小亮同志給的,妙計是放置在錦囊里,俗稱就是錦囊妙計嘛,那趙云就是一個干活的人,從錦囊中取出妙計,執行,然后獲勝,用 java 程序怎么表現這個呢?我們先看類圖:
三個妙計是同一類型的東東,那咱就寫個接口:
package com.oumyye.策略模式;/*** @author * I'm glad to share my knowledge with you all.* 首先定一個策略接口,這是諸葛亮老人家給趙云的三個錦囊妙計的接口**/public interface IStrategy { //每個錦囊妙計都是一個可執行的算法public void Operate();}
然后再寫三個實現類,有三個妙計嘛:
one
package com.oumyye.策略模式;/*** @author * I'm glad to share my knowledge with you all.* 找喬國老幫忙,使孫權不能殺劉備*/public class BackDoor implements IStrategy {public void operate() { System. out.two
package com.oumyye.策略模式;/*** @author * I'm glad to share my knowledge with you all.* 求吳國太開個綠燈*/public class GivenGreenLight implements IStrategy {public void operate() { System. out.println(" 求吳國太開個綠燈, 放行! "); }}three
package com.oumyye.策略模式;/*** @author* I'm glad to share my knowledge with you all.* 孫夫人斷后,擋住追兵*/public class BlockEnemy implements IStrategy {public void operate() { System. out.println(" 孫夫人斷后,擋住追兵"); }}好了,大家看看,三個妙計是有了,那需要有個地方放這些妙計呀,放錦囊呀:
package com.oumyye.策略模式;/*** @author * I'm glad to share my knowledge with you all.* 計謀有了,那還要有錦囊*/public class Context {//構造函數,你要使用那個妙計private IStrategy straegy;public Context(IStrategy strategy){ this. straegy = strategy; }//使用計謀了,看我出招了public void operate(){ this. straegy.operate(); }}然后就是趙云雄赳赳的揣著三個錦囊,拉著已步入老年行列的、還想著娶純情少女的、色迷迷的劉老爺子去入贅了,嗨,還別說,小亮的三個妙計還真是不錯,瞅瞅:
package com.oumyye.策略模式;/** * @author */public class ZhaoYun { /** * 趙云出場了,他根據諸葛亮給他的交代,依次拆開妙計 */ public static void main(String[] args) { Context context; // 剛剛到吳國的時候拆第一個 System.out.println("-----------剛剛到吳國的時候拆第一個-------------"); context = new Context(new BackDoor()); // 拿到妙計 context.operate(); // 拆開執行 System.out.println("/n/n/n/n/n/n/n/n"); // 劉備樂不思蜀了,拆第二個了 System.out.println("-----------劉備樂不思蜀了,拆第二個了-------------"); context = new Context(new GivenGreenLight()); context.operate(); // 執行了第二個錦囊了 System.out.println("/n/n/n/n/n/n/n/n"); // 孫權的小兵追了,咋辦?拆第三個 System.out.println("-----------孫權的小兵追了,咋辦?拆第三個-------------"); context = new Context(new BlockEnemy()); context.operate(); // 孫夫人退兵 System.out.println("/n/n/n/n/n/n/n/n"); /* * 問題來了:趙云實際不知道是那個策略呀,他只知道拆第一個錦囊,而不知道是BackDoor這個妙計,咋辦? * 似乎這個策略模式已經把計謀名稱寫出來了 * * 錯! BackDoor、 GivenGreenLight、 BlockEnemy只是一個代碼,你寫成first、 second、 * third,沒人會說你錯! * * 策略模式的好處就是:體現了高內聚低耦合的特性呀,缺點嘛,這個那個,我回去再查查 */ }}就這三招,搞的周郎是“陪了夫人又折兵”呀!這就是策略模式,高內聚低耦合的特點也表現出來了,還有一個就是擴展性,也就是 OCP 原則,策略類可以繼續增加下去,只要修改 Context.java 就可以了,這個不多說了,自己領會吧。
策略模式的優點:
- 相關算法系列Strategy類層次為Context定義了一系列的可供重用的算法或行為。繼承有助于析取出這些算法中的公共功能。
- 提供了可以替換繼承關系的辦法: 繼承提供了另一種支持多種算法或行為的方法。你可以直接生成一個Context類的子類,從而給它以不同的行為。但這會將行為硬行編制到 Context中,而將算法的實現與Context的實現混合起來,從而使Context難以理解、難以維護和難以擴展,而且還不能動態地改變算法。最后你得到一堆相關的類 , 它們之間的唯一差別是它們所使用的算法或行為。將算法封裝在獨立的Strategy類中使得你可以獨立于其Context改變它,使它易于切換、易于理解、易于擴展。
- 消除了一些if else條件語句:Strategy模式提供了用條件語句選擇所需的行為以外的另一種選擇。當不同的行為堆砌在一個類中時 ,很難避免使用條件語句來選擇合適的行為。將行為封裝在一個個獨立的Strategy類中消除了這些條件語句。含有許多條件語句的代碼通常意味著需要使用Strategy模式。
- 實現的選擇Strategy模式可以提供相同行為的不同實現。客戶可以根據不同時間 /空間權衡取舍要求從不同策略中進行選擇。
新聞熱點
疑難解答