設計模式學習--策略模式(Strategy Pattern)

本人最近也在學習設計模式,看到也是 HEAD_FIRST設計模式 ,所以,偷個懶,直接轉載個筆記。嘿嘿。

設計模式學習–策略模式(Strategy Pattern)
什麼是策略模式?
定義算法族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化獨立使用算法的客戶。

怎麼使用策略模式設計程序?
分開變化和不會變化的部分,建立一組新的類來代表變化的部分。

三個設計原則:
1. 找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起。
2. 針對接口編程,而不是針對實現編程。
3. 多用組合,少用繼承。

策略模式應用例子:
一隻鴨Duck,可能是以下幾種不同類型的鴨
(MallardDuck) 綠頭鴨–會飛會呱呱叫
(RedHeadDuck) 紅頭鴨–會飛會呱呱叫
(RubberDuck) 橡皮鴨–不會飛會嘰嘰叫
(DecoyDuck) 誘餌鴨–不會飛也不會叫
(ModelDuck) 模型鴨–不會飛也不會叫

在沒有使用策略模式之前可能這樣:

  1. 利用繼承來提供Duck的行爲
    ===》導致代碼在多個子類中重複
    ===》運行時的行爲不容易改變
    ===》很難知道所有鴨子的全部行爲
    ===》改變會牽一髮動全身,造成其他鴨子不想要的改變。
  2. 把會變的行爲提取出來設計成一個接口
    ===》導致重複代碼變多
    ===》導致代碼無法進行復用

使用策略模式會是這樣:
1. 採用良好的oo軟件設計原則
2. 分開變化和不會變化的部分
3. 針對接口編程

具體實現:
所有類型鴨的抽象:Duck類
[java] view plaincopy
package strategyPattern;

/**
* 所有類型鴨子的超類
* @author wwj
*
*/
public abstract class Duck {
FlyBehavior flyBehavior; //飛行行爲
QuackBehavior quackBehavior; //呱呱叫行爲

public void performQuack(){  
    quackBehavior.quack();  
}  

public void swim(){  
    System.out.println("All ducks float, even decoys!");  
}  

public abstract void display();  

public void performFly() {  
    flyBehavior.fly();  
}  

public void setFlyBehavior(FlyBehavior fb) {  
    flyBehavior = fb;  
}  

public void setQuackBehavior(QuackBehavior qb) {  
    quackBehavior = qb;  
}  

}

把會變化的部分取出並“封裝”起來,好讓其他部分不會受到影響
提供兩個接口FlyBehavior和QuackBehavior
[java] view plaincopy
package strategyPattern;

public interface FlyBehavior {
public void fly();
}

[java] view plaincopy
package strategyPattern;

public interface QuackBehavior {
public void quack();
}

實現鴨子的行爲(飛行類)
[java] view plaincopy
package strategyPattern;

public class FlyWithWings implements FlyBehavior {

@Override  
public void fly() {  
    //實現鴨子飛行  
    System.out.println("I'm flying!");  
}  

}

[java] view plaincopy
package strategyPattern;

public class FlyNoWay implements FlyBehavior {

@Override  
public void fly() {  
    //什麼都不做,不會飛  
    System.out.println("I can't fly");  
}  

}

[java] view plaincopy
public class FlyRocketPowered implements FlyBehavior {

@Override  
public void fly() {  
    System.out.println("I'm flying with a rocket!");  
}  

}

實現鴨子的行爲(呱呱叫)
[java] view plaincopy
package strategyPattern;

public class Quack implements QuackBehavior {

@Override  
public void quack() {  
    //實現鴨子呱呱叫  
    System.out.println("Quack");  
}  

}

[java] view plaincopy
package strategyPattern;

public class Squack implements QuackBehavior {

@Override  
public void quack() {  
    //橡皮鴨子嘰嘰叫  
    System.out.println("Squack");  
}  

}

[java] view plaincopy
package strategyPattern;

public class MuteQuack implements QuackBehavior {

@Override  
public void quack() {  
    // 什麼都不做,不會叫  
}  

}

整合鴨子的行爲,讓不同的鴨子繼承鴨類(Duck)
[java] view plaincopy
package strategyPattern;

/**
* 綠頭鴨繼承鴨類
* @author wwj
*
*/
public class MallardDuck extends Duck{

/** 
 * 因爲MallardDuck繼承Duck類,所以具有flyBehavior與quackBehavior實例變量 
 */  
public MallardDuck() {  
    quackBehavior = new Quack(); //真正的呱呱叫     
    flyBehavior = new FlyWithWings();   //會用翅膀飛  
}  

public void display() {  
    System.out.println("I'm a real Mallard duck");  //我是一個真正的綠頭鴨  
}  

}

[java] view plaincopy
package strategyPattern;

public class RedheadDuck extends Duck{
public RedheadDuck() {
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}

@Override  
public void display() {  
    System.out.println("I'm a RedheadDuck!!");  //紅頭鴨  
}  

}

[java] view plaincopy
package strategyPattern;

public class RubberDuck extends Duck{
public RubberDuck() {
}

@Override  
public void display() {  
    System.out.println("I'm a RubberDuck!!!");  
}  

}

[java] view plaincopy
package strategyPattern;

public class ModelDuck extends Duck {
public ModelDuck() {
flyBehavior = new FlyNoWay(); //不會飛
quackBehavior = new Quack(); //會嘰嘰叫
}

@Override  
public void display() {  
    System.out.println("I'm a model duck");  
}  

}

[java] view plaincopy
package strategyPattern;

public class DecoyDuck extends Duck{
public DecoyDuck(){
}

@Override  
public void display() {  
    System.out.println("I'm a DecoyDuck!!!");   //我是一隻誘餌鴨  
}  

}

測試類:
[java] view plaincopy
package strategyPattern;

public class MiniDuckSimulator {
public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.performQuack();
mallard.performFly();

    //動態改變模型鴨的行爲--通過調用繼承來的setter方法  
    Duck model = new ModelDuck();  
    model.performFly();  
    model.setFlyBehavior(new FlyRocketPowered());   //委託  
    model.performFly();  
}  

}

測試結果:
[java] view plaincopy
Quack
I’m flying!
I can’t fly
I’m flying with a rocket!

確實,使用策略模式之後,代碼變得可複用了,可以適應更多的變化,而不會互相影響。良好的oo設計必須具備可複用、可擴充、可維護三個特性。模式是前人歷經驗證的經驗,可以用來解決程序設計當中的各種問題。
轉載至:http://blog.csdn.net/wwj_748/article/details/8933282

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章