1. 程式人生 > >C++設計模式~裝飾模式(Decorator)

C++設計模式~裝飾模式(Decorator)

文章目錄

裝飾模式

我們需要把所需的功能按正確的順序串聯起來進行控制,比如 先穿衣服—>褲子—>鞋子—>領帶, 當然相反也可以

裝飾模式:動態地給一個物件新增一些額外的職責,就增加功能來說,裝飾模式比生成子類更為靈活

在這裡插入圖片描述

程式碼舉例

decorator.h

#ifndef DECORATOR_H
#define DECORATOR_H
#include <string>
#include <iostream>
using namespace std;

//裝飾模式
class Component
{
public:
    virtual void Operation() = 0;
};

class ConcreteComponent:public Component
{
public:
    void Operation();
};

class Decorator:public Component
{
public
: Component *component; void setComponent(Component *component); virtual void Operation() = 0; }; class ConcreteDecoratorA:public Decorator { public: void Operation(); private: string addedState; }; class ConcreteDecoratorB:public Decorator { public: void Operation(); private
: void addedBehavior(); }; #endif // DECORATOR_H

decorator.cpp

#include "decorator.h"


void Decorator::setComponent(Component *component)
{
    this->component = component;
}

void Decorator::Operation()
{
    if(this->component != nullptr)
    {
        this->component->Operation();
    }
}

void ConcreteComponent::Operation()
{
    cout<<"ConcreteComponent::Operation()"<<endl;
}

void ConcreteDecoratorA::Operation()
{
    this->component->Operation();//首先執行原Component的Operation()
    this->addedState = "new state";//再執行本類的功能,相當於對原Component進行了裝飾飾
    cout<<"ConcreteDecoratorA::Operation()"<<endl;
}

void ConcreteDecoratorB::Operation()
{
    this->component->Operation();//首先執行原Component的Operation()
    this->addedBehavior();//再執行本類的功能,相當於對原Component進行了裝飾飾
    cout<<"ConcreteDecoratorB::Operation()"<<endl;
}

void ConcreteDecoratorB::addedBehavior()
{
    cout<<"ConcreteDecoratorB::addedBehavior()"<<endl;
}

main.cpp

int main()
{
    ConcreteComponent *c = new ConcreteComponent();
    ConcreteDecoratorA *d1 = new ConcreteDecoratorA();
    ConcreteDecoratorB *d2 = new ConcreteDecoratorB();
    d1->setComponent(c);
    d2->setComponent(d1);
    d2->Operation();
    return 0;
}
  • 裝飾的方法是:首先用ConcreteComponent例項化物件c,然後用ConcreteDecoratorA 的例項化物件d1來包裝c,再用ConcreteDecoratorB 的物件d2包裝d1,最終執行d2的Operation()
  • 裝飾模式是利用SetComponent來對物件進行包裝的,這樣每個裝飾物件的實現就和如何使用這個物件分離開了,每個裝飾物件只關心自己的功能,不需要關心如何被新增到物件鏈當中,順序隨意,靈活的
  • 學習模式要善於變通,如果只有一個ConCreteComponent類而沒有抽象的Component類,那麼Decorator類可以是ConcreteComponent的一個子類,同樣道理,如果只有一個ConcreteDecorator類,那麼就沒必要建立一個單獨的Decorator類,而可以把Decorator和Concrete Decorator的責任合併成一個類

在這裡插入圖片描述

再舉例

在這裡插入圖片描述

person.h

#ifndef PERSON_H
#define PERSON_H
#include <iostream>
#include <string>
using namespace std;

//人類(ConcreteComponent)
class Person
{
private:
    string name;
public:
    Person(){}
    Person(string name)
    {
        this->name = name;
    }
    virtual void show()
    {
        cout<<"is "<<name<<endl;
    }
};

//服裝類(Decorator)
class Finery:public Person
{
protected:
    Person *component;
    //打扮
public:
    void Decorate(Person *component)
    {
        if(component != nullptr)
        {
            this->component = component;
        }
    }
    void show()
    {
        if(component != nullptr)
        {
            component->show();
        }
    }
};

//具體服裝類(ConcreteDecorator)
class TShirts:public Finery
{
public:
    void show()
    {
        cout<<"TShirts  ";
        this->component->show();
    }
};

class BigTrouser:public Finery
{
public:
    void show()
    {
        cout<<"BigTrouser  ";
        this->component->show();
    }
};

class Sneakers:public Finery
{
public:
    void show()
    {
        cout<<"Sneakers  ";
        this->component->show();
    }
};

#endif // PERSON_H

main.cpp

int main()
{
    Person *Nemo = new Person("Nemo");
    Sneakers *s = new Sneakers();
    BigTrouser *bt = new BigTrouser();
    TShirts *t = new TShirts();

    s->Decorate(Nemo);
    bt->Decorate(s);
    t->Decorate(bt);
    t->show();
    return 0;
}

結果顯示:TShirts BigTrouser Sneakers is Nemo

裝飾模式是為了已有功能動態地新增更多功能的一種方式。但是到底什麼時候用它呢?

當系統需要新功能的時候,是向舊的類中新增新的程式碼。這些新加的程式碼通常裝飾了原有類的核心職責或主要行為,比如用西服和鞋子裝飾小明,但這種做法的問題在於,它們在主類中加入了新的欄位,新的方法和新的邏輯,從而增加了主類的複雜度,就像最初設計了一個類,不考慮擴充套件的話,當有新需求的時候,而這些新加入的東西僅僅是為了滿足一些只在某種特定情況下才會執行的特殊行為的需要。而裝飾模式卻提供了一個非常好的解決方案,它把每個要裝飾的功能放在單獨的類中,並讓這個類包裝它所要裝飾的物件,因此,當需要執行特殊行為時,客戶端程式碼就可以在執行的時候根據需要有選擇地,按順序地使用裝飾功能包裝物件了

總結:裝飾模式的優點就是把類中的裝飾功能從類中搬移去除,這樣可以簡化原有的類,而且更有效地把類的核心職責和裝飾功能區分開了,而且可以去除相關類中的重複的裝飾邏輯