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

C++ 裝飾者模式完整實作:動態擴展物件行為的組合替代繼承方案

     編輯:關於C語言

裝飾者模式(Decorator Pattern)屬結構型設計模式,透過「組合」而非「繼承」在執行期動態為物件新增職責。本文提供完整 C++ 實作,包含 UML 類別圖對應程式碼、多層裝飾疊加示範、記憶體管理注意事項,並對比繼承方案優劣。

模式核心角色

角色類別職責
ComponentCHuman定義被裝飾者介面(虛函數 Info(), Level())
ConcreteComponentCLiaoningHuman, CShanDongHuman具體被裝飾物件
DecoratorDecorator繼承 Component,持有 Component 指標,定義裝飾介面
ConcreteDecoratorCDecoratorWuDang, CDecoratorShaoLin, CDecoratorHuaShan具體裝飾行為(武功流派)

完整 C++ 實作

#include <iostream>
#include <string>
using namespace std;

// ===== Component =====
class CHuman {
public:
    virtual ~CHuman() = default;
    virtual string Info() const { return "無資訊"; }
    virtual int Level() const = 0;           // 純虛函數
protected:
    string m_info;
};

// ===== ConcreteComponent =====
class CLiaoningHuman : public CHuman {
public:
    CLiaoningHuman() { m_info = "遼寧人"; }
    int Level() const override { return 0; }
};

class CShanDongHuman : public CHuman {
public:
    CShanDongHuman() { m_info = "山東人"; }
    int Level() const override { return 0; }
};

// ===== Decorator (抽象裝飾者) =====
class Decorator : public CHuman {
public:
    explicit Decorator(CHuman* human) : m_human(human) {}
    virtual ~Decorator() { delete m_human; }  // 負責釋放被裝飾者
    string Info() const override = 0;         // 強制子類實作
    int Level() const override = 0;
protected:
    CHuman* m_human;
};

// ===== ConcreteDecorators =====
class CDecoratorWuDang : public Decorator {
public:
    explicit CDecoratorWuDang(CHuman* h) : Decorator(h) {}
    string Info() const override { return m_human->Info() + " 學習了武當功夫"; }
    int Level() const override { return m_human->Level() + 1; }
};

class CDecoratorShaoLin : public Decorator {
public:
    explicit CDecoratorShaoLin(CHuman* h) : Decorator(h) {}
    string Info() const override { return m_human->Info() + " 學習了少林功夫"; }
    int Level() const override { return m_human->Level() + 2; }
};

class CDecoratorHuaShan : public Decorator {
public:
    explicit CDecoratorHuaShan(CHuman* h) : Decorator(h) {}
    string Info() const override { return m_human->Info() + " 學習了華山功夫"; }
    int Level() const override { return m_human->Level() + 3; }
};

客戶端測試:多層裝飾疊加


int main() {
    // 遼寧人 → 武當 → 少林 → 華山
    CHuman* person = new CLiaoningHuman();
    person = new CDecoratorWuDang(person);
    person = new CDecoratorShaoLin(person);
    person = new CDecoratorHuaShan(person);

    cout << person->Info() << endl;  // 遼寧人 學習了武當功夫 學習了少林功夫 學習了華山功夫
    cout << "武功等級: " << person->Level() << endl;  // 6

    // 山東人 → 武當 → 少林
    person = new CShanDongHuman();
    person = new CDecoratorWuDang(person);
    person = new CDecoratorShaoLin(person);

    cout << person->Info() << endl;  // 山東人 學習了武當功夫 學習了少林功夫
    cout << "武功等級: " << person->Level() << endl;  // 3

    // 記憶體由最外層 Decorator 析構遞歸釋放
    delete person;
    return 0;
}

關鍵設計細節

  1. 虛解構子:CHuman 與 Decorator 必須宣告 virtual ~ClassName(),確保多層裝飾正確釋放記憶體。
  2. 所有權語意:Decorator 建構子接收裸指標並接管所有權,析構時 delete m_human。現代 C++ 建議改用 std::unique_ptr<CHuman> 明確語意。
  3. 介面一致性:裝飾者繼承 CHuman,對客戶端呈現相同介面,實現透明疊加。
  4. 單一職責:每個裝飾類別只負責一種武功擴展,符合開放封閉原則(OCP)。

裝飾者 vs 繼承對比

維度繼承裝飾者模式
靈活度編譯期靜態決定執行期動態組合
類別爆炸排列組合產生大量子類線性新增裝飾類別
多重行為疊加需多重繼承(複雜)自然支援鏈式疊加
封裝性破壞封裝(存取 protected)僅透過公共介面互動

適用場景

  • 需要在不修改既有類別的前提下,動態、透明地擴展物件功能。
  • 功能擴展組合多變,若用繼承會導致子類別數量爆炸(如 GUI 視窗加邊框、捲軸、陰影等任意組合)。
  • 職責可分割為核心功能與多個可選增強(如 Java I/O BufferedReader, GZIPInputStream 疊加)。

總結

裝飾者模式以「組合優於繼承」為核心哲學,提供比繼承更彈性的擴展機制。掌握其「抽象裝飾者持有元件介面、具體裝飾者轉呼叫並增強」的結構範本,即可優雅解決動態功能疊加問題。現代 C++ 實作時請搭配智慧指標管理生命週期,避免手動 new/delete 風險。

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