装饰模式(大话设计模式例子C++实现)

1 概述

装饰模式:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。有时我们希望给某个对象而不是整个类添加一些功能。比如有一个电脑(人),允许你为电脑添加特性,比如添加键盘、鼠标垫等(穿衣服)。一种灵活的设计方式是,将电脑(人)嵌入到另一对象中,由这个对象完成特性的添加,我们称这个嵌入的对象为装饰。这个装饰与它所装饰的组件接口一致,因此它对使用该组件的客户透明。下面给出装饰模式的UML图。
在这里插入图片描述

  • Component是定义一个对象接口,可以给这些对象动态的添加职责
  • ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责
  • Decorator抽象装饰类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无序知道Decorator的存在的
  • ConcreteDecorator是具体的装饰类,起到给Component添加职责的功能
  • 如果只有一个ConcreteComponent类而没有抽象的类,那么Decorator可以是ConcreteComponent的一个子类。
  • 同样,如果只有一个ConcreteComponent类,那么没有必要建立一个单独的Decorator 类,而可以把Decorator和ConcreteComponent的责任合成一个类
  • 装饰的方法是:首先用ConcreteComponent实例化一个对象C,然后用ConcreteComponentA实例化一个对象d1来包装 C,再用ConcreteComponentB实例化一个对象d2来包装 d1,最后执行d2的Operation()

2 电脑配件实现

请添加图片描述

在这种设计中,电脑(人)的装饰功能被独立出来,可以单独发展,进而简化了具体电脑类的设计。下面给出类的实现:

//公共抽象类
class Computer
{
    
    
public:
	Computer() {
    
    }
	virtual ~Computer() {
    
    }
	virtual void ShowDecorate() {
    
    }
};
//具体的电脑类
class DellComputer : public Computer
{
    
    
private:
	string m_name; //电脑名称
public:
	DellComputer(string name): m_name(name){
    
    }
	~DellComputer() {
    
    }
	virtual void ShowDecorate() {
    
     cout<<m_name<<"的装饰"<<endl;}//virtual可写可不写
};
//装饰类
class DecoratorComputer : public Computer
{
    
    
private:
	Computer *m_computer;  //要装饰的手机
public:
	DecoratorComputere(Computer *m_computer): m_computer(computer) {
    
    }
	virtual void ShowDecorate() {
    
     m_computer->ShowDecorate(); }
};
//具体的装饰类
class DecoratorA : public DecoratorComputer
{
    
    
public:
	DecoratorA(Computer *m_computer) : DecoratorComputer(computer) {
    
    }
	void ShowDecorate() {
    
     DecoratorComputer::ShowDecorate(); AddDecorate(); }
private://本类独有的方法,以区别其他具体装饰类
	void AddDecorate() {
    
     cout<<"增加挂件1"<<endl; } //增加的装饰
};
//具体的装饰类
class DecoratorB : public DecoratorComputer
{
    
    
public:
	DecoratorB(Computer *m_computer) : DecoratorComputer(computer) {
    
    }
	void ShowDecorate() {
    
     DecoratorComputer::ShowDecorate(); AddDecorate(); }
private:
	void AddDecorate() {
    
     cout<<"增加挂件2"<<endl; } //增加的装饰
};

首先用DellComputer实例化一个对象computer,然后用DecoratorA实例化一个对象dpa来包装 computer,再用DecoratorA实例化一个对象dpb来包装 dpa,最后执行dpb的ShowDecorate()

int main()
{
    
    
	Computer *computer = new DellComputer("xxxx");
	Computer *dpa = new DecoratorA(computer); //装饰,增加挂件1
	Computer *dpb = new DecoratorB(dpa);    //装饰,增加挂件2
	dpb->ShowDecorate();
	delete dpa;
	delete dpb;
	delete computer;
	return 0;
}

3 人穿衣搭配代码实现

下面的例子是一个人搭配穿衣的问题,因为只有一个ConcreteComponent类(只有一个具体的人:xiaocai)而没有抽象的类,所以把Decorator看作ConcreteComponent的一个子类。
在这里插入图片描述

#include <iostream>
using namespace std;
class Person{
    
    
public:
    Person(){
    
    }
    Person(string name){
    
    
        this->m_name = name;
        cout << "我是" << m_name << endl;
    }
    virtual void show(){
    
    }
    virtual ~Person(){
    
    }
private:
    string m_name;
};
//服饰类(装饰器)
class Finery:public Person{
    
    
protected:
    Person  *component;
public:
    void Decorate(Person *component){
    
    
        this->component = component;
    }
    virtual void show(){
    
    
    	component->show();
    }
};

//具体服饰类
class TShirts:public Finery{
    
    
    
public:
    virtual void show(){
    
    
        Finery::show();//为什么与下句顺序翻一下就不可以
        cout << "大体恤 " << endl;
    }
};
//具体服饰类
class Sneakers:public Finery{
    
    
    
public:
    virtual void show(){
    
    
        Finery::show();
        cout << "球鞋 " << endl;
    }
};
//具体服饰类
class BigTrouser:public Finery{
    
    
    
public:
    virtual void show(){
    
    
        Finery::show();
        cout << "垮裤 " << endl;
    }
};

int main(){
    
    
    Person* xc = new Person("xiaocai");
    cout << "第一种装扮:" << endl;
    Sneakers* pgx = new Sneakers();
    BigTrouser* kk = new BigTrouser();
    TShirts *dtx = new TShirts();

    pgx->Decorate(xc);
    kk->Decorate(pgx);
    dtx->Decorate(kk);
    dtx->show();

    return 0;
}

在这里插入图片描述

具体服饰类中

 virtual void show(){
    
    
        Finery::show();//为什么与下句顺序翻一下就不可以
        cout << "大体恤 " << endl;
    }

为什么与下句顺序翻一下就不可以?
首先运行Finery::show(),再运行本类功能cout << “大体恤” << endl;相当于对原来的Finery进行了装饰。

Guess you like

Origin blog.csdn.net/weixin_44515978/article/details/119817911