本人最近也在學習設計模式,看到也是 HEAD_FIRST設計模式 ,所以,偷個懶,直接轉載個筆記。嘿嘿。
設計模式學習–策略模式(Strategy Pattern)
什麼是策略模式?
定義算法族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化獨立使用算法的客戶。
怎麼使用策略模式設計程序?
分開變化和不會變化的部分,建立一組新的類來代表變化的部分。
三個設計原則:
1. 找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起。
2. 針對接口編程,而不是針對實現編程。
3. 多用組合,少用繼承。
策略模式應用例子:
一隻鴨Duck,可能是以下幾種不同類型的鴨
(MallardDuck) 綠頭鴨–會飛會呱呱叫
(RedHeadDuck) 紅頭鴨–會飛會呱呱叫
(RubberDuck) 橡皮鴨–不會飛會嘰嘰叫
(DecoyDuck) 誘餌鴨–不會飛也不會叫
(ModelDuck) 模型鴨–不會飛也不會叫
在沒有使用策略模式之前可能這樣:
- 利用繼承來提供Duck的行爲
===》導致代碼在多個子類中重複
===》運行時的行爲不容易改變
===》很難知道所有鴨子的全部行爲
===》改變會牽一髮動全身,造成其他鴨子不想要的改變。 - 把會變的行爲提取出來設計成一個接口
===》導致重複代碼變多
===》導致代碼無法進行復用
使用策略模式會是這樣:
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