2010年11月3日 星期三

[OO 設計模式] Strategy Pattern : 策略模式 - 封裝演算法 (Encapsulating algorithm)

前言 : 
在Head First - Design Pattern 一書, 第一章介紹的就是 Strategy Pattern. 在這裡首先以一個 Duck 類別開始進行說明. 在進行演進過程首先碰到當我們需要對 Duck 擴充使之具有 fly 的行為 (或函式) 時, 第一個我們直覺得就會在父類直接添加該 fly 的行為, 但這個動作卻造成所有 Duck 的子類都有 fly 的行為 (就連 DecoyDuck 都可以 fly =="), 似乎不太合理, 因此接下來便引進了 Strategy Pattern 並將 fly 與 接下來的 quack 行為從父類解偶合出來另外兩個介面 FlyBehavior 與 QuackBehavior. 而不同的 fly 與 quack 行為則實現這兩個介面進行客製化的實作. 而在整個文章有提到一些設計原則說明如下 : 

Design Principle : 

- Program to an interface, not an implementation.
- Identify the aspects of your application what vary and seperate them from what stays the same.
- Favor composition over inheritance.


Strategy Pattern 定義 : 
The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.


範例說明 : 
如同前言提到的, 在Duck 類別需要擴充 fly 與 quack 行為時, 與其直接新增行為在 Duck 類別上, 這裡採用的是使用介面 FlyBehavior 與 QuackBehavior 來封裝各種不同的 fly 與 quack 行為 (封裝演算法). 這裡符合設計原則的 : Favor composition over inheritance. 實際的UML 設計圖如下 : 
 

範例代碼 : 
這裡並未詳列所有代碼, 全部代碼請參考附件. 
* Duck 類別代碼 : 
  1. package hf.dp.ch01;  
  2.   
  3. import hf.dp.ch01.behavior.FlyBehavior;  
  4. import hf.dp.ch01.behavior.QuackBehavior;  
  5.   
  6. public class Duck {  
  7.     private String name;  
  8.     protected QuackBehavior quack = null;  
  9.     protected FlyBehavior fly = null;  
  10.       
  11.     public Duck(String n){  
  12.         name = n;  
  13.     }  
  14.       
  15.     public void display(){  
  16.         System.out.println("\tThis is "+name +" Duck!");  
  17.     }  
  18.       
  19.     public void performFly(){  
  20.         if(fly!=null) {  
  21.             fly.fly();  
  22.         }  
  23.     }  
  24.       
  25.     public void performQuack(){  
  26.         if(quack!=null) {  
  27.             quack.Quack();  
  28.         }  
  29.     }  
  30.   
  31.     public void setName(String name) {  
  32.         this.name = name;  
  33.     }  
  34.   
  35.     public void setQuack(QuackBehavior quack) {  
  36.         this.quack = quack;  
  37.     }  
  38.   
  39.     public void setFly(FlyBehavior fly) {  
  40.         this.fly = fly;  
  41.     }  
  42.           
  43. }  
* QuackBehavior 介面代碼 : 
  1. package hf.dp.ch01.behavior;  
  2.   
  3. public interface QuackBehavior {  
  4.     public void Quack();  
  5. }  
* FlyBehavior 介面代碼 : 
  1. package hf.dp.ch01.behavior;  
  2.   
  3. public interface FlyBehavior {  
  4.     public void fly();  
  5. }  
* RedHeadDuck 類別代碼 : 
  1. package hf.dp.ch01;  
  2.   
  3. import hf.dp.ch01.behavior.FlyWithWings;  
  4. import hf.dp.ch01.behavior.Quack;  
  5.   
  6. public class RedHeadDuck extends Duck{  
  7.   
  8.     public RedHeadDuck(String n) {  
  9.         super(n);  
  10.         quack = new Quack();  
  11.         fly = new FlyWithWings();  
  12.     }  
  13. }  
* 演示設計模式代碼 : 
  1. package hf.dp.ch01;  
  2.   
  3. import hf.dp.ch01.behavior.*;  
  4.   
  5. public class Main {  
  6.     public static void main(String args[]) {  
  7.         Duck duck1 = new RubberDuck("Rubber Duck");  
  8.         duck1.display();  
  9.         duck1.performFly();  
  10.         duck1.performQuack();  
  11.         duck1 = new DecoyDuck("Decoy Duck");  
  12.         duck1.display();  
  13.         duck1.performFly();  
  14.         duck1.performQuack();  
  15.         duck1 = new RedHeadDuck("Red Head Duck");  
  16.         duck1.display();  
  17.         duck1.performFly();  
  18.         duck1.performQuack();  
  19.         /*Dynamically change behavior of duck*/  
  20.         duck1.setFly(new FlyWithNoWing());  
  21.         duck1.setQuack(new MuteQuack());  
  22.         duck1.display();  
  23.         duck1.performFly();  
  24.         duck1.performQuack();  
  25.     }  
  26. }  


補充說明 : 
* Strategy Pattern from Wiki : 
In computer programming, the strategy pattern (also known as the policy pattern) is a particular software design pattern, whereby algorithms can be selected at runtime.

* Design Patterns 第三炮 : 實作Strategy Pattern,讓元件像USB一般隨插即用!(網路文章) 
Strategy Patten的用途是當我們在設計系統,面對需要彈性抽換商業邏輯或者演算法議題時,用來將客戶端以及演算法的物件之間鬆綁的解決方式,用比較容易理解的說法,我們可以說Strategy就如同是一個Switch在運作著,使得系統可以在不同的演算法之間作彈性切換。

沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...