閱讀267 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Design Pattern: Strategy 模式

  學習是分享和合作式的!

轉載請注明出處:https://blog.csdn.net/wdzxl198/article/details/9306775

文章摘自: https://www.riabook.cn/doc/designpattern/

考慮您要設計一個更換各種符號的工具類TextCharChange,您是否會采用這樣的方式:

   1: public void replace() {
   2:    switch(getChangeType()) {
   3:       case RN_TYPE:  
   4:                 replaceRN();
   5:                 break;
   6:       case N_TYPE: 
   7:                 replaceN();
   8:                 break;
   9:       case OTHER_TYPE: 
  10:                 replaceOTHER():
  11:                 break;
  12:       ...
  13:    }
  14: }

這麼作的缺點是,日後您要增加更換符號的策略時,會有幾個地方需要修改:增加TYPE常數、增加TextCharChange中的 replaceXXX()方法、增加 replace()方法中的switch case判斷。
像這種策略采用的情況,可以將策略加以封裝為一個物件,而不是將策略寫死在某個類中,如此一來,策略可以獨立於客戶端,隨時增加變化、增加或減少策略,即使是修改每個策略的內容,也不會對客戶端程式造成影響。
來舉個最簡單的例子,首先要知道Windows與Linux的文字檔案換行符號是不同的,Windows是 /r/n ,而Linux是 /n,今天您要設計一個文字編輯器,在適當的時候,您必須要能隨時轉換這兩種符號,如果不采用上麵的策略采用流程的話,要如何設計:

  • TextStrategy.java
   1: public abstract class TextStrategy { 
   2:     protected String text;
   3:  
   4:     public TextStrategy(String text) { 
   5:         this.text = text; 
   6:     }
   7:  
   8:     public abstract String replace(); 
   9: }  
  • LinuxStrategy.java

   1: public class LinuxStrategy extends TextStrategy { 
   2:     public LinuxStrategy(String text) { 
   3:         super(text); 
   4:     }
   5:  
   6:     public String replace() { 
   7:         preOperation(); 
   8:         System.out.println(
   9:                text = text.replaceAll("@r@n", "@n")); 
  10:         postOperation(); 
  11:  
  12:         return text; 
  13:     }
  14:  
  15:     private void preOperation() { 
  16:         System.out.println("LinuxStrategy preOperation"); 
  17:     }
  18:  
  19:     private void postOperation() { 
  20:         System.out.println("LinuxStrategy postOperation"); 
  21:     } 
  22: } 

  • WindowsStrategy.java
   1: public class WindowsStrategy extends TextStrategy { 
   2:     public WindowsStrategy(String text) { 
   3:         super(text); 
   4:     }
   5:  
   6:     public String replace() { 
   7:         startOperation(); 
   8:         System.out.println(
   9:                      text = text.replaceAll("@n", "@r@n")); 
  10:         endOperation(); 
  11:  
  12:         return text; 
  13:     }
  14:  
  15:     private void startOperation() { 
  16:         System.out.println("WindowsStrategy startOperation"); 
  17:     } 
  18:  
  19:     private void endOperation() { 
  20:         System.out.println("WindowsStrategy endOperation"); 
  21:     } 
  22: } 
  • TextCharChange.java

   1: public class TextCharChange { 
   2:     public static void replace(TextStrategy strategy) { 
   3:         strategy.replace(); 
   4:     } 
   5: }

  • Main.java

   1: public class Main { 
   2:     public static void main(String[] args) { 
   3:         String linuxText = 
   4:             "This is a test text!!@n Oh! Line Return!!@n"; 
   5:         String windowsText = 
   6:             "This is a test text!!@r@n Oh! Line Return@r@n"; 
   7:  
   8:         // load file, suppose it's Linux's text file 
   9:         // take the WindowsStrategy 
  10:         // I want to change it to Windows' text file 
  11:         TextCharChange.replace(
  12:               new WindowsStrategy(linuxText)); 
  13:  
  14:         // such-and-such operation..... 
  15:         System.out.println(); 
  16:  
  17:         // load file, suppose it's Windows' text file 
  18:         // take the LinuxStrategy 
  19:         // I want to change it to Linux's text file 
  20:         TextCharChange.replace(
  21:             new LinuxStrategy(windowsText)); 
  22:     } 
  23: }

為了明顯的秀出結果,我們使用@n來表示 '/n' , @r 表示 '/r' 符號,Main中的流程是個假設的情況,何時采用何種策略是隨機的。
在Strategy模式中,使用一個公開的介麵replace(),讓客戶端請求,而在實作replace()時,可以任意的組合演算策略,程式中的 preOperation()、postOperation()就是用以示意演算的組合概念,Strategy模式封裝了這些演算過程,使它們易於組合、 修改、替換,上麵這個例子的UML 類別結構圖如下所示:

Strategy

Strategy模式的UML類別結構圖如下:

Strategy

從行為上來說,State 模式 與Strategy模式是相近的。
State模式:看當前是什麼狀態,就采取什麼動作。
Strategy模式:看需求(情境)是什麼,采用適當的策略。
不過兩者雖相似,應用的場合稍有不同,State模式中有一個重點在於設定狀態變化,就像 Gof 例子中舉的TCP連線;Strategy策略模式則是直接采用適當的策略的感覺,例如Gof中說的,采用適當的演算法來作正文換行。

Edit by Atlas,

Time:09:50

最後更新:2017-04-03 16:48:33

  上一篇:go HDFS基礎概念
  下一篇:go C# 網絡編程之套接字編程基礎知識