2018-09-19 17:11:22ios
裝飾模式就是在不改變原有類以及不使用繼承的狀況下給原有類動態的增長一些額外的職責。編程
Tips:不要和建造者模式混淆,建造者模式要求建造的過程是穩定的,可是裝飾者模式這個裝扮的方式並非穩定的,有些裝扮過程甚至無關緊要。例如QQ秀的形象裝扮。(感謝大話設計模式的做者給出如此優秀的實例以理解裝飾模式)設計模式
Component:定義一個對象方法的虛基類,能夠給這些對象動態的添加職責。 //Component實際上就是須要被裝飾的類的基類架構
ConcreteComponent:定義一個具體的對象,也能夠給這個對象添加一些職責。ide
Decorator:裝飾者基類,它和Component是一種聚合關係,就是說它有一個成員是Component類型的。它繼承了 Component,從外類來擴展Compoment類的功能,但對於Component來講,它是不須要知道Decorator的存在的。spa
ConcreteDecorator:就是具體的裝飾帝鄉,起到給Component添加職責的功能。.net
解析:這個例子就是模擬了一我的裝扮的過程,首先人有頭、身體、身高、所處背景這四個基本屬性。如今咱們要經過裝飾者模式,給它添加職責,例如給頭帶一個圓帽子、背景設置爲海灘、身高設置爲40四、身體上給穿一套禮服,這個是裝飾過程就是ConcreteDecorator作的事情,那麼具體要裝飾誰呢,要裝飾的對象就是ConcreteComponent。設計
1.Component類指針
#ifndef COMPONENT_H_ #define COMPONENT_H_ #include <string> class Component { public: virtual const std::string& getHeadMode() const = 0; virtual const std::string& getBodyMode() const = 0; virtual const int getHeight() const = 0; virtual const std::string& getHairStyle() const = 0; virtual const std::string& getName() const = 0; virtual void setHeadMode(const std::string strHeadMode) {}; virtual void setBodyMode(const std::string strBodyMode) {}; virtual void setHeight(const int iHeight) {}; virtual void setHairStyle(const std::string strHairStyle){}; virtual void setName(const std::string strName){}; Component() = default; virtual ~Component() = default; protected: int m_iHeight{0}; std::string m_strName; std::string m_strHeadMode; std::string m_strBodyMode; std::string m_strHairStyle; }; #endif
2.具體Component類,這個也是修飾者將要修飾的對象code
#ifndef CONCRETECOMPONENT_H_ #define CONCRETECOMPONENT_H_ #include "Component.h" #include <string> class ConcreteComponent:public Component { public: void setName(const std::string strName) { m_strName = strName; } void setHeight(const int iHeight) { m_iHeight = iHeight; } void setHeadMode(const std::string strHeadMode) { m_strHeadMode = strHeadMode; } void setBodyMode(const std::string strBodyMode) { m_strBodyMode = strBodyMode; } void setHairStyle(const std::string strHairStyle) { m_strHairStyle = strHairStyle; } const std::string& getHeadMode() const override { return m_strHeadMode; } const std::string& getBodyMode() const override { return m_strBodyMode; } const int getHeight() const override { return m_iHeight; } const std::string& getHairStyle() const { return m_strHairStyle; } const std::string& getName() const { return m_strName; } ConcreteComponent() = default; ~ConcreteComponent() = default; }; #endif
3.裝飾者基類:從Component繼承而來,並持有一個Component類型的成員指針
#ifndef DECORATOR_H_ #define DECORATOR_H_ #include "Component.h" class Decorator:public Component { public: const std::string& getHeadMode() const override { return m_strHeadMode; } const std::string& getBodyMode() const override { return m_strBodyMode; } const int getHeight() const override { return m_iHeight; } const std::string& getHairStyle() const override { return m_strHairStyle; } const std::string& getName() const override { return m_strName; } virtual void decorate(Component *) =0; virtual void show() = 0; Decorator() = default; virtual ~Decorator()=default; protected: Component* m_objRole{nullptr}; }; #endif
4.具體裝飾者,負責裝飾具體Component類。本例中這個裝飾者負責給小人傳衣服。若是還要裝飾其它的,例如換個髮型,那麼就須要在實現一個新的具體裝飾者(ConcreteDecorator)類,並在客戶端代碼裏調用它的decorate成員進行裝飾。
#ifndef ADDDRESS_H_ #define ADDDRESS_H_ #include "Decorator.h" #include <iostream> class AddDress:public Decorator { public: void decorate(Component *objRole); void show(); AddDress(const std::string strDress):m_strDress(strDress){}; AddDress() = default; ~AddDress() = default; private: std::string m_strDress; }; #endif #include "AddDress.h" void AddDress::decorate(Component* objRole) { m_objRole = objRole; if(m_objRole != nullptr) { std::string strDress = objRole->getBodyMode() + m_strDress; objRole->setBodyMode(strDress); } } void AddDress::show() { if(nullptr != m_objRole) std::cout << m_objRole->getName() << "dress a " << m_objRole->getBodyMode() << std::endl; }
5.客戶端代碼,使用2和4中的類,對ConcreteComponent進行裝飾。
#include "ConcreteComponent.h" #include "AddDress.h" using namespace std; int main(int argc,char *argv[]) { ConcreteComponent objConcreteComponent; objConcreteComponent.setName("yang yang"); objConcreteComponent.setHeight(160); AddDress objDress(" Skirt"); objDress.decorate(&objConcreteComponent); objDress.show(); return(1); }
我以爲使用這個示例來講明裝飾者模式略微有些牽強。
裝飾模式是爲已有功能動態的添加更多功能的一種方式。當系統須要新功能時,能夠經過向舊的類中添加新代碼(違背了開放-封閉原則),這些新加的代碼一般裝飾了原有類的核心職責或者主要行爲,在主類中增長新的字段,新的方法和新的邏輯,增長了主類的複雜度,而新加入的東西僅僅是爲了知足一些只在某種特定狀況下才會執行的特殊行爲的須要(功能的動態加入和刪除)。針對這種狀況,裝飾模式提供了比繼承更好或者比修改原來相對較好的方式。它把每一個要裝飾的功能放在單獨的類中,並讓這個類包裝它所要裝飾的對象,所以當須要執行特殊行爲時,客戶端代碼就能夠在運行時根據須要有選擇地、按順序的使用裝飾功能包裝對象。因此裝飾模式的優勢就是,把類的裝飾功能從類中搬移去除,這樣能夠簡化原有的類。而且能有效的把類的核心職責和裝飾功能區分開。能夠去除相關類中的重複裝飾邏輯。
裝飾者模式優缺點部分來自:https://blog.csdn.net/liang19890820/article/details/66973836(還沒實際使用過,但能夠想到它的缺點)
優勢:
缺點:
使用場景: