标題定義:
動态地給一個對象添加一些額外的職責。就增加功能來說,裝飾模式比生成子類更為靈活。
結構
裝飾模式有以下4個角色。
■ 抽象構件(Component)角色:該角色用于規範需要裝飾的對象(原始對象)。
■ 具體構件(Concrete Component)角色:該角色實作抽象構件接口,定義一個需要裝飾的原始類。
■ 裝飾(Decorator)角色:該角色持有一個構件對象的執行個體,并定義一個與抽象構件接口一緻的接口。
■ 具體裝飾(Concrete Decorator)角色:該角色負責對構件對象進行裝飾。
應用
裝飾模式類似于一個嵌套調用,就像俄羅斯套娃,裝飾者的執行函數,會調用被裝飾者的執行函數,多層裝飾就存在多重調用。
在一般情況下,裝飾模式可以避免在衆多不同類别的屬性下因為繼承帶來的類爆炸問題。在Head First設計模式一書中,為不同飲料和配料建立不同子類就出現了類爆炸:
使用裝飾模式,可以避免反複耦合建立子類,隻需要使用不同的分類裝飾就可以了。重構後的類圖如下:
示例
幾本書上都是java版本的代碼,是以想自己寫一個C++的示例,沒想到因為通路父類變量的問題卡了好久。隻要新增一個set接口來設定一個公有變量。
#include <iostream>
using namespace std;
class Phone
{
public :
virtual void show() = 0;
};
class iPhone:public Phone{
public :
virtual void show()
{
cout<<"iPhone"<<endl;
}
};
class DecoratorPone:public Phone
{
public :
void setBasePhone(Phone* phone)
{
mPhone = phone;
}
virtual void show()
{
mPhone->show();
}
Phone* mPhone;
};
class PhoneSuit:public DecoratorPone
{
public:
PhoneSuit(Phone* phone)
{
setBasePhone(phone);
}
virtual void show()
{
cout<<"帶上套套的";
mPhone->show();
}
};
class PhoneScreen:public DecoratorPone
{
public:
PhoneScreen(Phone* phone)
{
setBasePhone(phone);
}
virtual void show()
{
cout<<"貼上鋼化膜的";
mPhone->show();
}
};
int main() {
Phone* myPhone = new iPhone();
cout<<"這是一個";myPhone->show();
myPhone = new PhoneSuit(myPhone);
cout<<"這是一個";myPhone->show();
myPhone = new PhoneScreen(myPhone);
cout<<"這是一個";myPhone->show();
return 0;
}
輸出:
這是一個iPhone
這是一個帶上套套的iPhone
這是一個貼上鋼化膜的帶上套套的iPhone
線上網址:
打開網址可以線上編譯哦!點選我吧!
選擇edit:
之後點選submit :
參考書目:
- 設計模式之禅(第2版)作者:秦小波出版社:機械工業出版社
- 設計模式:Java版 作者:青島東合資訊技術有限公司出版社:電子工業出版社
- 大話設計模式 吳強 企業管理出版社
- Head First設計模式(中文版) [美] 弗裡曼 中國電力出版社
- 菜鳥教程 https://www.runoob.com/design-pattern/decorator-pattern.html