文章目录
学习设计模式的主要目的是为了学习整个软件开发的思维逻辑, 这是上百年程序员大佬们总结出来的精华, 就像学好数理化走遍天下都不怕是一个逻辑, 我永远相信, 业务开发跟设计模式息息相关, 个人思维逻辑与算法息息相关, 活到老, 学到老, 与君共勉即努力.
- 平台 win10子系统
Ubuntu18.04
- 编译器
gcc dbg
- 编辑器
VScode
1. 先验知识
- 子类继承父类初始化父类:
子类构造函数(参数) : 父类构造函数(父类构造函数参数){}
- 子类使用父类中的成员:
父类名::父类成员
2. 装饰器模式相关概念
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
按照人话讲: 就是先实例化一个对象, 在给这个对象增加新的功能, 比继承更加灵活的操作
意图: 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
何时使用:在不想增加很多子类的情况下扩展类。
如何解决:将具体功能职责划分,同时继承装饰者模式。
关键代码: 1、Component 类充当抽象角色,不应该具体实现。 2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。
应用实例: 1、孙悟空有 72 变,当他变成"庙宇"后,他的根本还是一只猴子,但是他又有了庙宇的功能。 2、不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。
使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。
注意事项:可代替继承。
3. 装饰器模式的应用
3.1 应用1: 给形状添加新的特征 不同形状加红
创建形状, 拥有方形和圆形, 又想要给方形和圆形染色为红色, 按照以往的逻辑, 需要给方形和圆形在增加对应的子类, 在子类里面增加红色, 但是在这里, 我们尝试换一种思路, 增加一个形状子类命名为抽象装饰器类, 里面创建对应的形状对象, 这样当传入的不管是圆还是方形, 都在这个类里面增加染为红色的方法, 这样就实现了装饰器的功能
#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