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

策略模式深度解析:以鴨子模型為例,掌握組合優於繼承的設計智慧

     編輯:Java 程式設計入門

問題場景:繼承帶來的維護噩夢

假設我們要模擬各種鴨子:綠頭鴨、橡皮鴨、誘餌鴨。初期用繼承:

abstract class Duck { void quack(); void fly(); }
class MallardDuck extends Duck { ... }
class RubberDuck extends Duck { 
    // 問題:橡皮鴨不會飛、叫聲是吱吱
    @Override void fly() { /* 什麼都不做 */ }
    @Override void quack() { System.out.println("吱吱"); }
}

缺點顯而易見:

  • 代碼重複:每新增一種鴨子,可能都要重寫 fly/quack。
  • 運行時行為固化:無法動態讓誘餌鴨「學會飛行」。
  • 行為分散:難以掌握所有鴨子的完整行為清單。
  • 牽一髮動全身:修改父類方法可能波及所有子類。

設計原則:找出變化,封裝變化

「找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混合在一起。」

將 fly 和 quack 從 Duck 中提取,定義為介面:

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

具體策略實現

// 飛行策略
class FlyWithWings implements FlyBehavior { 
    public void fly() { System.out.println("我會飛"); } 
}
class FlyNoWay implements FlyBehavior { 
    public void fly() { System.out.println("我不會飛"); } 
}

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

鴨子基類:組合 + 委派

abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
    
    public void performFly() { flyBehavior.fly(); }
    public void performQuack() { quackBehavior.quack(); }
    
    // 關鍵:提供設置器,支援運行時動態變更行為
    public void setFlyBehavior(FlyBehavior fb) { flyBehavior = fb; }
    public void setQuackBehavior(QuackBehavior qb) { quackBehavior = qb; }
    
    abstract void display(); // 外觀差異由子類實現
}

具體鴨子:配置而非繼承

class MallardDuck extends Duck {
    public MallardDuck() {
        flyBehavior = new FlyWithWings();
        quackBehavior = new Quack();
    }
    public void display() { System.out.println("我是綠頭鴨"); }
}

class DecoyDuck extends Duck {
    public DecoyDuck() {
        flyBehavior = new FlyNoWay();
        quackBehavior = new MuteQuack();
    }
    public void display() { System.out.println("我是誘餌鴨"); }
}

客戶端驗證:動態變更行為

public class MiniDuckSimulator {
    public static void main(String[] args) {
        Duck mallard = new MallardDuck();
        mallard.performQuack(); // 輸出: 呱呱
        
        // 運行時動態改變:綠頭鴨突然失聲了
        mallard.setQuackBehavior(new MuteQuack());
        mallard.performQuack(); // 輸出: 沉默
    }
}

核心設計原則總結

  1. 針對介面編程,而非實現:Duck 依賴 FlyBehavior 介面,而非具體類。
  2. 多用組合,少用繼承:行為通過組合注入,而非繼承獲得。行為可復用(青蛙也能用 Quack),可動態替換。
  3. 封裝變化:演算法族 (策略) 獨立演變,不影響使用它的客戶 (Duck)。

策略模式定義

定義了演算法族,分別封裝起來,讓它們之間可以相互替換。此模式讓演算法的變化獨立於使用演算法的客戶。

適用場景:同一行為有多種實現 (如支付方式、排序算法、壓縮策略、路由規則),且需在運行時切換。

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