C++设计模式 装饰器模式

文章目录

学习设计模式的主要目的是为了学习整个软件开发的思维逻辑, 这是上百年程序员大佬们总结出来的精华, 就像学好数理化走遍天下都不怕是一个逻辑, 我永远相信, 业务开发跟设计模式息息相关, 个人思维逻辑与算法息息相关, 活到老, 学到老, 与君共勉即努力.

  • 平台 win10子系统 Ubuntu18.04
  • 编译器 gcc dbg
  • 编辑器 VScode

1. 先验知识

  • 子类继承父类初始化父类: 子类构造函数(参数) : 父类构造函数(父类构造函数参数){}
  • 子类使用父类中的成员: 父类名::父类成员

2. 装饰器模式相关概念

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

按照人话讲: 就是先实例化一个对象, 在给这个对象增加新的功能, 比继承更加灵活的操作

意图: 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。

何时使用:在不想增加很多子类的情况下扩展类。

如何解决:将具体功能职责划分,同时继承装饰者模式。

关键代码: 1、Component 类充当抽象角色,不应该具体实现。 2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。

应用实例: 1、孙悟空有 72 变,当他变成"庙宇"后,他的根本还是一只猴子,但是他又有了庙宇的功能。 2、不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。

优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

缺点:多层装饰比较复杂。

使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。

注意事项:可代替继承。

3. 装饰器模式的应用

3.1 应用1: 给形状添加新的特征 不同形状加红

创建形状, 拥有方形和圆形, 又想要给方形和圆形染色为红色, 按照以往的逻辑, 需要给方形和圆形在增加对应的子类, 在子类里面增加红色, 但是在这里, 我们尝试换一种思路, 增加一个形状子类命名为抽象装饰器类, 里面创建对应的形状对象, 这样当传入的不管是圆还是方形, 都在这个类里面增加染为红色的方法, 这样就实现了装饰器的功能

C++设计模式 装饰器模式

#include <iostream>
#include <algorithm>
using namespace std;

// 创建形状抽象类
class Shape{
public:
    virtual void draw() = 0;
};

// 创建圆类
class Rectangle : public Shape{
public:
    void draw(){
        cout << "create Rectangle ... " <<endl;
    }
};

// 创建方类
class Circle : public Shape{
public:
    void draw(){
        cout << "create Circle ... " <<endl;
    }
};

// 创建修饰器的抽象类, 里面先包含一个形状, 然后给这个形状后面再添加功能
class ShapeDecorator : public Shape{
protected:
    Shape *decoratedShape = nullptr; // 创建一个基础形状, 并在修饰器初始化时初始化这个形状

public:
    ShapeDecorator(Shape *decoratedShape): decoratedShape(decoratedShape){}
    virtual void draw()=0;
};

// 创建扩展了ShapeDecorator类的实体装饰类 将形状颜色变为红色
class RedShapeDecorator : public ShapeDecorator{
public:
    // 显示的初始化父类的成员变量 
    RedShapeDecorator(Shape *decoratedShape) : ShapeDecorator(decoratedShape){}  
    
    void draw(){
        ShapeDecorator::decoratedShape->draw();  // 显式使用父类成员变量, 好像没啥用   
        setRedBorder(ShapeDecorator::decoratedShape); // 然后给在调用增加功能也就是red颜色
   }
 
private:
    void setRedBorder(Shape *decoratedShape){
        cout << "border color : rrred" <<endl;
    }
};
int main(int argc, char const *argv[])
{
    Shape *circle = new Circle(); // 形状创建一个圆, 多态
    ShapeDecorator *redCircle = new RedShapeDecorator(new Circle()); // 创建一个红圆
    ShapeDecorator *redRectangle = new RedShapeDecorator(new Rectangle()); // 创建一个红正方
    // Shape *redCircle = new RedShapeDecorator(new Circle());
    // Shape *redRectangle = new RedShapeDecorator(new Rectangle());
    cout << "实验一: 创建一个普通的圆, 并打印" << endl;
    circle->draw();

    cout << "实验二: 创建一个带有红边的圆" <<endl;
    redCircle->draw();

    cout << "实验二: 创建一个带有红边的方" <<endl;
    redRectangle->draw();
}
  • 结果
实验一: 创建一个普通的圆, 并打印
create Circle ... 
实验二: 创建一个带有红边的圆
create Circle ... 
border color : rrred
实验二: 创建一个带有红边的方
create Rectangle ... 
border color : rrred
上一篇:python numpy库总结


下一篇:utils->frame->vue->shape