首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

《Head First 設計模式》讀書筆記:從鴨子模擬器看策略模式——封裝變化、針對介面編程、多用組合

     編輯:Java 綜合教學

場景:不斷變化的鴨子需求

初始設計:Duck 抽象類定義 quack()、fly()、swim(),子類繼承覆寫。問題:

  • 新增 RubberDuck(不會飛、吱吱叫)→ 需覆寫 fly() 為空、quack() 改行為
  • 新增 DecoyDuck(不會飛、不會叫)→ 又要覆寫兩方法
  • 未來可能:火箭動力飛、噴火叫、隱形鴨……每新增一種行為組合就要新建子類,類爆炸

嘗試 1:介面分離(失敗)

定義 Flyable、Quackable 介面,會飛/會叫的子類實現。缺點:代碼無法復用,每個子類仍需各自實現介面方法,維護成本不降反增。

核心設計原則

找出應用中可能變化的部分,把它們獨立出來,不要和那些不變的混在一起。
—— 封裝變化

針對介面編程,而不是針對實現編程。
—— 多態與解耦

多用組合,少用繼承。
—— 靈活性與復用

策略模式重構

1. 定義行為介面

public interface FlyBehavior { void fly(); }
public interface QuackBehavior { void quack(); }

2. 具體行為實現(算法族)

// 飛行
public class FlyWithWings implements FlyBehavior { public void fly() { System.out.println("用翅膀飛"); } }
public class FlyNoWay implements FlyBehavior { public void fly() { System.out.println("不會飛"); } }
public class FlyRocketPowered implements FlyBehavior { public void fly() { System.out.println("火箭動力飛行!"); } }

// 叫聲
public class Quack implements QuackBehavior { public void quack() { System.out.println("呱呱叫"); } }
public class Squeak implements QuackBehavior { public void quack() { System.out.println("吱吱叫"); } }
public class MuteQuack implements QuackBehavior { public void quack() { System.out.println("沉默"); } }

3. Duck 基類組合行為

public abstract class Duck {
    protected FlyBehavior flyBehavior;
    protected QuackBehavior quackBehavior;

    public Duck() {
        this.flyBehavior = new FlyWithWings(); // 預設行為
        this.quackBehavior = new Quack();
    }

    public void performFly() { flyBehavior.fly(); }
    public void performQuack() { quackBehavior.quack(); }
    public void swim() { System.out.println("游泳"); }
    public abstract void display();

    // 運行時動態改變行為
    public void setFlyBehavior(FlyBehavior fb) { this.flyBehavior = fb; }
    public void setQuackBehavior(QuackBehavior qb) { this.quackBehavior = qb; }
}

4. 具體鴨子只關注外觀

public class MallardDuck extends Duck {
    public MallardDuck() {
        // 可選:在構造器指定特定行為
    }
    public void display() { System.out.println("綠頭鴨"); }
}

public class RubberDuck extends Duck {
    public RubberDuck() {
        setFlyBehavior(new FlyNoWay());
        setQuackBehavior(new Squeak());
    }
    public void display() { System.out.println("黃色橡皮鴨"); }
}

5. 客戶端動態切換

Duck modelDuck = new ModelDuck();
modelDuck.performFly(); // 不會飛
modelDuck.setFlyBehavior(new FlyRocketPowered());
modelDuck.performFly(); // 火箭動力飛行!

策略模式結構圖

策略模式UML 行為封裝示意

總結

維度繼承方案介面方案策略模式(組合)
代碼復用低(需覆寫)無(各自實現)高(行為類復用)
靈活性編譯時固定編譯時固定運行時動態切換
類數量指數增長線性增長行為類 + 鴨子類,正交
符合原則違反封裝變化部分符合完美符合三大原則

策略模式定義了算法族,封裝每個算法,使它們可互換,讓算法變化獨立於使用算法的客戶。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved