動態地**給對象添加職責**,無需修改原類代碼,且裝飾可任意組合、疊加。是繼承的靈活替代方案,完美體現「對修改關閉,對擴展開放」 (OCP)。
coreFunction1/2) 與擴展介面 (dosomething)。ConcreteComponentA/B/C),實現核心邏輯與基礎 dosomething。Component* 指針,轉發調用。OneDecorator/TwoDecorator/ThreeDecorator,在轉發前後添加具體裝飾邏輯。
class Component {
public:
virtual ~Component() = default;
void coreFunction1() { cout << "核心方法1\n"; }
void coreFunction2() { cout << "核心方法2\n"; }
virtual void dosomething() = 0; // 擴展點
};
class ConcreteComponentA : public Component {
public:
void dosomething() override { cout << "A類\n"; }
};
class ConcreteComponentB : public Component {
public:
void dosomething() override { cout << "B類\n"; }
};
class ConcreteComponentC : public Component {
public:
void dosomething() override { cout << "C類\n"; }
};
class Decorator : public Component {
protected:
Component* component; // 持有被裝飾對象
public:
explicit Decorator(Component* comp) : component(comp) {}
void dosomething() override { component->dosomething(); } // 默認透傳
};
class OneDecorator : public Decorator {
public:
using Decorator::Decorator;
void dosomething() override {
Decorator::dosomething(); // 調用被裝飾者
cout << "添加了裝飾方法1\n";
}
};
class TwoDecorator : public Decorator {
public:
using Decorator::Decorator;
void dosomething() override {
Decorator::dosomething();
cout << "添加了裝飾方法2\n";
}
};
class ThreeDecorator : public Decorator {
public:
using Decorator::Decorator;
void dosomething() override {
Decorator::dosomething();
cout << "添加了裝飾方法3\n";
}
};
int main() {
// 層層包裝:A 先加 3,再加 2,再加 1
Component* obj1 = new OneDecorator(
new TwoDecorator(
new ThreeDecorator(
new ConcreteComponentA)));
obj1->dosomething();
obj1->coreFunction1();
obj1->coreFunction2();
// 另一種組合:B 先加 1,再加 3
Component* obj2 = new ThreeDecorator(
new OneDecorator(
new ConcreteComponentB));
obj2->dosomething();
obj2->coreFunction1();
obj2->coreFunction2();
// 記得釋放 (或用 unique_ptr 管理)
delete obj1; // 需遞歸刪除,建議用智能指針
delete obj2;
}
A類 添加了裝飾方法3 添加了裝飾方法2 添加了裝飾方法1 核心方法1 核心方法2 B類 添加了裝飾方法1 添加了裝飾方法3 核心方法1 核心方法2
#include
using ComponentPtr = std::unique_ptr;
class Decorator : public Component {
ComponentPtr component; // 獨佔所有權
public:
explicit Decorator(ComponentPtr comp) : component(std::move(comp)) {}
void dosomething() override { component->dosomething(); }
};
// 使用
auto obj = std::make_unique(
std::make_unique(
std::make_unique(
std::make_unique())));
// 自動釋放,無需手動 delete
| 維度 | 繼承 | 裝飾者 | 策略模式 |
|---|---|---|---|
| 靜態/動態 | 編譯期靜態 | 運行時動態組合 | 運行時動態切換 |
| 組合方式 | 單一繼承鏈 | 層層包裝,任意排列 | 整體替換算法對象 |
| 核心邏輯復用 | 基類實現 | 轉發被裝飾對象 | Context 委託 Strategy |
| 適用場景 | is-a 關係穩定 | 需疊加/移除職責 | 算法族可互換 |
std::ostream 裝飾 std::ofstream、std::ostringstream (Java BufferedReader 同理)。JScrollPane 包裝 JTextArea)。裝飾者模式以**組合替代繼承**,將單一職責拆分為獨立裝飾類,通過介面統一、指針持有、轉發調用實現行為疊加。C++ 實現關鍵點:虛析構、抽象裝飾類持有 Component 指針、具體裝飾類調用基類轉發再添加邏輯、客戶端構建裝飾鏈。配合 unique_ptr 實現 RAII 管理,代碼既優雅又安全。