策略模式(java)

來源:互聯網
上載者:User

標籤:名稱   代碼結構   ati   class   上下文   設計   image   body   解決   

引

  GOF 《設計模式:可複用物件導向軟體設計的基礎》中的模式,應當算是模式歸納的鼻祖(並非他們最早發現/使用了模式,而是將已有的模式進行了整合歸納),而我們現在對於模式的學習基本上都是基於Gof的設計模式。今天主要說說行為型模式中的一個:策略模式。

模式定義

  意圖:定義一系列的演算法,把它們一個個封裝起來,並且使它們可相互替換。本模式使得演算法可獨立於使用它的客戶而變化。

 

  動機:

  •   客戶程式如果直接包含策略演算法代碼,將會變得很複雜。(策略演算法本身足夠複雜)
  •   不同的時候需要不同的演算法   (if....else....)
模式類圖

闡述與討論

  策略模式是我們在開發中常用的模式之一。網上關於策略模式也有很多介紹,這裡再次提出,是期望給出“正規”的模式,在我初學設計模式時,也經常會被搞得不知所云,眾說紛紜還給出代碼,但幾乎都不太一樣,我也曾被策略模式搞得迷糊(主要是context),因此再次找出GOF原本進行分析- -

  最常見的疑惑問題:策略模式和簡單原廠模式進行比較。兩者區別還是比較大的,不管是從語義還是實現上。

  下面給出簡單工廠的類圖(GOF模式中沒有簡單工廠---只有抽象工廠和Factory 方法):

  

  對比簡單工廠和策略模式類圖很容易發現區別: 工廠(Factory)是依賴Product介面,同時依賴於具體產品(ProductA和ProductB),而策略模式中,Context是包含了Stategy介面,同時並不依賴具體的策略類。

通過代碼很容易就可以看出區別:

  策略模式代碼:

 1
 1 package strategydemo; 2 /** 3  * @author : xiaolu 2018年2月6日 4  * @todo   : 策略上下文 5  */ 6 public class Context { 7     // 內含項目關聯性 8     private Strategy strategy ;  9     // 這個類中包含具體策略需要的其他參數,必要時可以將自己傳遞給策略類(GOF)10     public Context(Strategy strategy){11         this.strategy = strategy;12     }13     14     public int get(){15         return this.strategy.algorithm();16     }17 }

 

 1 package strategydemo; 2  3 /** 4  * @author : xiaolu 2018年2月6日 5  * @todo   : 策略介面 6  */ 7 public class StrategyB implements Strategy { 8     @Override 9     public int algorithm() {10         // 這裡的邏輯應當比較複雜,否則沒有必要使用原則類11         // 僅作說明12         return 0;13     }14 15 }
 1 package strategydemo; 2  3 public class StrategyA implements Strategy { 4     @Override 5     public int algorithm() { 6         // 這裡的邏輯應當比較複雜,否則沒有必要使用原則類 7         // 僅作說明 8         return 1; 9     }10 11 }
 1 package strategydemo; 2  3 /** 4  * @author : xiaolu 2018年2月6日 5  * @todo   : 策略介面 6  */ 7 public class StrategyB implements Strategy { 8     @Override 9     public int algorithm() {10         // 這裡的邏輯應當比較複雜,否則沒有必要使用原則類11         // 僅作說明12         return 0;13     }14 15 }
 1 package strategydemo; 2 /** 3  * @author : xiaolu 2018年2月6日 4  * @todo   : 用戶端 5  */ 6 public class Main { 7     public static void main(String[] args) { 8         // 具體策略類 9         Strategy a = new StrategyA();10         //Context11         Context ctx = new Context(a);12         13         System.out.println(ctx.get());14     }15 }

代碼結構和名稱大體按照策略類圖所給出的。可以看到用戶端是“知道”(或者說依賴於)具體策略類的。而Context對於具體策略類並不存在任何依賴(無知),只是“包含”(類中屬性)了策略介面。

下面給出簡單工廠實現:

1 package simplefactory;2 3 /**4  * @author : xiaolu 2018年2月6日5  * @todo :產品介面6  */7 public interface Product {8     // ...... 原廠模式中,工廠主要用於產生產品,並不涉及產品的操作,因此此處省略具體產品的操作9 }
1 package simplefactory;2 3 /**4  * @author : xiaolu 2018年2月6日5  * @todo   : 產品A6  */7 public class ProductA implements Product {8 9 }
package simplefactory;/** * @author : xiaolu 2018年2月6日 * @todo   : 產品B */public class ProductB implements Product {}
 1 package simplefactory; 2  3 /** 4  * @author : xiaolu 2018年2月6日 5  * @todo   : 簡單工廠 6  */ 7 public class Factory { 8     // 傳回值為產品介面 9     public Product get(int i) {10         if (i == 0) {11             // 返回具體的產品(有依賴)12             return new ProductA();13         } else if (i == 1) {14             // 返回具體的產品(有依賴)15             return new ProductB();16         } else {17             throw new RuntimeException("不支援");18         }19     }20 }
 1 package simplefactory; 2  3 /** 4  * @author : xiaolu 2018年2月6日 5  * @todo   : 用戶端 6  */ 7 public class Main { 8     public static void main(String[] args) { 9         Factory f = new Factory();10         // 用戶端不知道(不依賴)具體產品11         Product p = f.get(1);12         // 執行p的操作13     }14 }

對比類圖和代碼實現,應該從結構上很容易區分兩者。更重要的是:策略模式是行為型模式,而原廠模式是建立型模式!通俗的說,原廠模式只負責產生“按你所需”的產品,至於你如何使用,工廠是無知的(這也是我為什麼沒有在產品介面中定義方法,因為不固定)。而策略模式中,具體的策略類是用戶端“知道”的(這也是是否需要直接使用原則模式的一個選擇【也可以規避它-策略+工廠】),而Context則負責“轉寄”(只是轉寄嗎?)這裡不妨想想,為什麼需要Context,如果沒有Context會如何呢?如果沒有:

1 Strategy strategy = new StrategyA();
2 strategy.algorithm();

好像還反而簡單了?Context是Strategy和Main(用戶端)之間的一個間接層,可以用來封裝需要傳遞給Strategy的資料結構和參數。

 

  相對於普通的多態結構,策略模式強調的是【演算法】的可相互替代性。再次強調:如果具體策略類並不複雜就不要用策略模式(自找煩惱)。而策略類的一個弊端:用戶端類需要“知道”具體策略類------可以通過加一個工廠解決。簡單工廠的意義是什麼呢? 符合SRP,單一職能,降低耦合 ,還有一個作用---------轉換。大部分的if....else代碼我們並不能規避,只是從“這裡”移到了“那裡”,好處是代碼更明確,更清晰,更容易擴充,而簡單工廠做這種轉換非常的合適。- -

 

策略模式(java)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.