Strategy策略設計模式

一、策略模式和狀態模式的區別和聯繫(本部分轉載自:http://letscoding.cn/java%E4%B8%AD%EF%BC%8C%E7%8A%B6%E6%80%81%E6%A8%A1%E5%BC%8F%E5%92%8C%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F%E7%9A%84%E5%8C%BA%E5%88%AB/)html

策略模式經過封裝一組相關算法,爲Client提供運行時的靈活性。Client能夠在運行時,選擇任一算法,而不改變使用算法的Context。一些流行的策略模式的例子是寫那些使用算法的代碼,例如加密算法、壓縮算法、排序算法。另外一方面,狀態模式容許對象,在不一樣的狀態擁有不一樣的行爲。由於現實世界中的對象一般都是有狀態的,因此它們在不一樣狀態,行爲也不同。例如,VM(自動售貨機)只在hasCoin狀態纔給你吐商品;你不投幣,它是不會吐的。如今你能夠清楚的看出它們的不一樣之處了:它們的意圖是不一樣的。狀態模式幫助對象管理狀態,而策略模式容許Client選擇不一樣的行爲。 java

另外一個不那麼容易能看出來的區別是:是誰促使了行爲的改變。策略模式中,是Client提供了不一樣的策略給Context;狀態模式中,狀態轉移由Context或State本身管理。另外,若是你在State中管理狀態轉移,那麼它必須持有Context的引用。例如,在VM的例子中,State對象須要調用VM的setState()方法去改變它的狀態。另外一方面,Strategy從不持有Context的引用,是Client把所選擇的Strategy傳遞給Context。因爲狀態模式和策略模式的區別,是流行的Java設計原則類面試題之一,咱們將會在本文探討在Java中,狀態模式和策略模式的異同,這能夠加深你對它們的理解。面試

類似之處算法

若是你看看狀態模式和策略模式的UML圖,就會發現它們的結構很是類似。使用State對象改變本身行爲的對象被稱爲Context對象;類似的,使用Strategy對象改變本身行爲的對象叫Context對象。記住,Client和Context打交道。在狀態模式中,Context把方法調用委託給當前的狀態對象,而在策略模式中,Context使用的Strategy對象,是被當作參數傳遞過來的,或在Context對象被建立時就被提供的。ide

讓咱們來看看它們之間更多的類似之處:加密

  1. 添加新的狀態或策略都很容易,並且不須要修改使用它們的Context對象。
  2. 它們都讓你的代碼符合OCP原則。在狀態模式和策略模式中,Context對象對修改是關閉的,添加新的狀態或策略,都不須要修改Context。
  3. 正如狀態模式中的Context會有初始狀態同樣,策略模式一樣有默認策略。
  4. 狀態模式以不一樣的狀態封裝不一樣的行爲,而策略模式以不一樣的策略封裝不一樣的行爲。
  5. 它們都依賴子類去實現相關行爲。

不一樣之處spa

如今咱們知道,狀態模式和策略模式的結構是類似的,但它們的意圖不一樣。讓咱們重溫一下它們的主要不一樣之處:設計

  1. 策略模式封裝了一組相關算法,它容許Client在運行時使用可互換的行爲;狀態模式幫助一個類在不一樣的狀態顯示不一樣的行爲。
  2. 狀態模式封裝了對象的狀態,而策略模式封裝算法或策略。由於狀態是跟對象密切相關的,它不能被重用;而經過從Context中分離出策略或算法,咱們能夠重用它們。
  3. 在狀態模式中,每一個狀態經過持有Context的引用,來實現狀態轉移;可是每一個策略都不持有Context的引用,它們只是被Context使用。
  4. 策略實現能夠做爲參數傳遞給使用它的對象,例如Collections.sort(),它的參數包含一個Comparator策略。另外一方面,狀態是Context對象本身的一部分,隨着時間的推移,Context對象從一個狀態轉移到另外一個狀態。
  5. 雖然它們都符合OCP原則,策略模式也符合SRP原則(單一職責原則),由於每一個策略都封裝本身的算法,且不依賴其餘策略。一個策略的改變,並不會致使其餘策略的變化。
  6. 另外一個理論上的不一樣:策略模式定義了對象「怎麼作」的部分。例如,排序對象怎麼對數據排序。狀態模式定義了對象「是什麼」和「何時作」的部分。例如,對象處於什麼狀態,何時處在某個特定的狀態。
  7. 狀態模式中很好的定義了狀態轉移的次序;而策略模式並沒有此須要:Client能夠自由的選擇任何策略。
  8. 一些常見的策略模式的例子是封裝算法,例如排序算法,加密算法或者壓縮算法。若是你看到你的代碼須要使用不一樣類型的相關算法,那麼考慮使用策略模式吧。而識別什麼時候使用狀態模式是很簡單的:若是你須要管理狀態和狀態轉移,但不想使用大量嵌套的條件語句,那麼就是它了。
  9. 最後但最重要的一個不一樣之處是,策略的改變由Client完成;而狀態的改變,由Context或狀態本身。

本段譯自:Difference between State and Strategy Design Pattern in Javacode

二、URL圖下載地址(astah/jude):http://pan.baidu.com/s/1hqy0c88orm

三、示例

公共策略規範接口

1 package com.xinye.test.strategy;
2 /**
3  * 策略通用接口
4  * @author xinye
5  *
6  */
7 public interface IStrategy {
8     public void strategy();
9 }

默認策略

 1 package com.xinye.test.strategy;
 2 /**
 3  * 默認Strategy
 4  * @author xinye
 5  *
 6  */
 7 public class NormalStrategy implements IStrategy {
 8 
 9     @Override
10     public void strategy() {
11         System.out.println(getClass().getSimpleName() + " strategy()");
12     }
13 
14 }

第一種策略

package com.xinye.test.strategy;
/**
 * 第一種Strategy
 * @author xinye
 *
 */
public class FirstStrategy implements IStrategy {

    @Override
    public void strategy() {
        System.out.println(getClass().getSimpleName() + " strategy()");
    }

}

第二種策略

 1 package com.xinye.test.strategy;
 2 /**
 3  * 第二種Strategy
 4  * @author xinye
 5  *
 6  */
 7 public class SecondStrategy implements IStrategy {
 8 
 9     @Override
10     public void strategy() {
11         System.out.println(getClass().getSimpleName() + " strategy()");
12     }
13 
14 }

策略Context

 1 package com.xinye.test.strategy;
 2 /**
 3  * 策略模式Context
 4  * @author xinye
 5  *
 6  */
 7 public class Context {
 8     
 9     private IStrategy strategy = new NormalStrategy();
10     /**
11      * 須要客戶端把策略傳遞過來
12      * @param s
13      */
14     public void exec(IStrategy s){
15         strategy = s;
16         strategy.strategy();
17     }
18 }

客戶端代碼

package com.xinye.test.strategy;
/**
 * 客戶端代碼
 * @author xinye
 *
 */
public class Client {
    public static void main(String[] args) {
        
        Context context = new Context();
        // 傳遞給Context特定的策略
        context.exec(new NormalStrategy());
        // 傳遞給Context特定的策略
        context.exec(new FirstStrategy());
        // 傳遞給Context特定的策略
        context.exec(new SecondStrategy());
    }
}

執行結果NormalStrategy strategy()FirstStrategy strategy()SecondStrategy strategy()

相關文章
相關標籤/搜索