案例來自--Head First設計模式
1.最初項目需求是:
設計鴨子模擬遊戲,有不同的鴨子,紅頭鴨,綠頭鴨。鴨子都會呱呱叫,但是外表不同
--設計思路
----肯定是使用面向對象的設計思路,設計一個鴨子超類,外表設計爲抽象方法
2.後來項目需求改了
需要鴨子會飛,並且鴨子有可能是橡皮玩具鴨,會叫不會飛;誘餌鴨,不會叫不會飛
--設計思路
----在超類裏增加會飛的動作,這樣的話每個鴨子都會飛,所以在不會飛鴨子裏覆蓋這個方法,讓不會飛的鴨子不飛--壞的設計思路
----將“會飛”動作設計爲接口,讓會飛的鴨子實現這個接口。看起來不錯,但是無法複用代碼,兩個鴨子都會飛,代碼要寫兩次--不太好的思路
----分析:將變化的部分抽出來。設計會飛接口、呱呱叫接口、鴨子類(沒有飛和叫)。很多個會飛接口的實現:不會飛,真的會飛和呱呱叫接口的實現:不會叫,呱呱叫,嘟嘟叫。
鴨子類裏有成員變量會飛接口對象,呱呱叫接口對象,通過接口對象調用接口的方法。這樣,具體的鴨子類(紅頭鴨,橡皮鴨)的構造函數裏去初始化接口對象(new),這樣如果要增加新的鴨子,如太空鴨,只需要增加新的飛、叫接口的實現即可
3.總結:
策略模式是定義一系列可以替換的算法族(就是一系列的接口的實現類),同一算法族內的實現類可以互相替換(例如都是某個接口的實現,myFly = new CanFly()換爲myFly = new NoFly()),讓算法的變化獨立於使用算法的客戶(Duck類)
代碼如下:
bad設計模式
package bad;
public class RedHeadDuck extends Duck {
public static void main(String[] args) {
RedHeadDuck aredDuck = new RedHeadDuck();
aredDuck.dispaly();
aredDuck.quack();
}
@Override
public void dispaly() {
System.out.println("我是紅頭鴨");
}
}
package bad;
public class RedHeadDuck extends Duck {
public static void main(String[] args) {
RedHeadDuck aredDuck = new RedHeadDuck();
aredDuck.dispaly();
aredDuck.quack();
}
@Override
public void dispaly() {
System.out.println("我是紅頭鴨");
}
}
好的設計模式
package good;
public class Duck {
public FlyBehaver myFly;
public QuackBehaver myQuack;
// 讓子類去初始化myFly myQuack
public Duck(){
}
public void swim(){
System.out.println("我會游泳");
}
public void show(){
myFly.fly();
myQuack.quack();
}
}
package good;
public interface FlyBehaver {
public void fly();
}
package good;
public interface QuackBehaver {
public void quack();
}
package good.fly;
import good.FlyBehaver;
public class CanFly implements FlyBehaver {
@Override
public void fly() {
System.out.println("我真的會飛");
}
}
package good.fly;
import good.FlyBehaver;
public class NoFly implements FlyBehaver {
@Override
public void fly() {
System.out.println("我不會飛");
}
}
package good.quack;
import good.QuackBehaver;
public class GuaGua implements QuackBehaver {
@Override
public void quack() {
System.out.println("呱呱叫");
}
}
package good.quack;
import good.QuackBehaver;
public class NoQuack implements QuackBehaver {
@Override
public void quack() {
System.out.println("我不會叫");
}
}
package good;
import good.fly.CanFly;
import good.quack.GuaGua;
public class RedHeadDuck extends Duck {
public RedHeadDuck(){
myFly = new CanFly();
myQuack = new GuaGua();
}
public static void main(String[] args) {
RedHeadDuck aDuck = new RedHeadDuck();
aDuck.show();
}
}