设计模式-装饰模式

发布时间 2023-03-29 14:35:27作者: 王清河

简介

+ 动态的给对象添加一些额外的职责,就增加功能来说,要比生成子类更加灵活

使用场景

+ 在不影响其他对象的情况下,以透明、动态的方式给单个对象添加职责;
+ 处理可以撤销的职责
+ 在不能采用生成子类的方法进行扩充时。
	- 可能有大量独立的扩展,为支持的每一种组合将产生大量的子类,使得子类数量很多
	- 类定义被隐藏,或者类兴义不能用于生成子类

角色

+ component
	- 抽象类,是具体对象和装饰类的父类
+ ConcreteComponent
	- 具体的对象类
+ Decorator
	- 维持一个指向 component 抽象类的指针,并继承对应的虚函数
+ ConcreteDecorator
	- 重新虚函数对应的罗

UML 类图

时序图

优缺点

+ 比静态继承更灵活
+ 避免在层次结构高层的类有太多的特征
+ Decorator 和它的 Component 不一样
+ 有许多小对象

代码实现

  • 给定两种初始的汽车类,分别使用装饰模式给它们添加新的功能。
#include<iostream>
#include<string>
using namespace std;

// abstract component class
class Car
{
public:
    virtual void showInfo() = 0;
};


// concrete component class 
class TOYOTO : public Car
{
public:
    TOYOTO(){}
    TOYOTO(string name) {
        m_name = name;
    }
    void showInfo(){
        cout << m_name << endl;
    }
private:
    string m_name;
};

class VOLOVL : public Car
{
public:
    VOLOVL(){}
    VOLOVL(string name) {
        m_name = name;
    }
    void showInfo(){
        cout << m_name << endl;
    }
private:
    string m_name;
};

// abstract decorator
class Function : public Car
{
protected:
    Car* m_pCar;
public:
    void Decorate(Car* pCar){
        m_pCar = pCar;
    }
    void showInfo(){
        if(m_pCar != NULL){
            m_pCar->showInfo();
        }
    }
};

// concrete decorator
class Navigator : public Function
{
public:
    void showInfo(){
        cout << "Navigator: ";
        Function::showInfo();
    }
};

// automatic drive
class AutoDrive : public Function
{
public:
    void showInfo(){
        cout << "AutoDrive: ";
        Function::showInfo();
    }
};

// speech control
class SpeechControl : public Function
{
public:
    void showInfo(){
        cout << "SpeechControl: ";
        Function::showInfo();
    }
};

int main()
{
    Car* p_CToyota = new TOYOTO("toyoto");
    Navigator* p_CNavi = new Navigator();
    AutoDrive* p_CAuto = new AutoDrive();
    p_CNavi->Decorate(p_CToyota);
    p_CAuto->Decorate(p_CNavi);
    p_CAuto->showInfo();

    Car* p_CVolo = new VOLOVL("Volovo");
    Navigator* p_CNa2 = new Navigator();
    SpeechControl* p_CSpeech = new SpeechControl();
    p_CNa2->Decorate(p_CVolo);
    p_CSpeech->Decorate(p_CNa2);
    p_CSpeech->showInfo();

    return 0;
}

总结

+ 在客户端中要最后一个添加的职责,用来包装好的车对象,因此需要最后一个装饰的实例显示结果