在做面向对象的软件开发时我们往往想达到更高的代码可复用性和更合理的软件颗粒度。
根据《设计模式——可复用面向对象软件的基础》所说:“你必须找到相关的对象,以适当的颗粒度将他们回归类,再定义类的接口和继承层次,建立对象之间的基本关系。你的设计应该对手头的问题有针对性,同时对将来的问题和需求也要有足够的通用性。”
内行的设计者知道:不是解决任何问题都要从头做起。他们更愿意复用以前使用的解决方案。这些重复的模式方案解决特定的问题,使得面向对象的设计更灵活、优雅,最终复用性更好。它们帮助设计者将新的设计建立在以往的工作基础上,复用以往的成功设计方案。一个熟悉这些设计模式的设计者不需要再去发现它们,而能够立即将他们应用于设计问题中。
本系列文章主要参考文献为——设计模式,可复用面向对象软件的基础(Design Patterns Elements of Reusable Object-Oriented SoftWare Erich.),内部代码基本用C++语言编写。
汇总链接:23种设计模式C++实现——概要(索引汇总)
摘要
本章主要说明装饰者模式,该设计模式主要意图是:动态的给一些对象添加一些额外的职责,相比于继承子类更加灵活。
有的时候我们想给某个对象增加一些功能(而不是给整个类增加功能,不需要通过定义子类添加新的类实现),例如一个普通滑块增加立体效果,在一个普通样式增加花纹。
具体实现下边我们就通过一个小栗子来说明什么是装饰者模式。
主要参与者
该设计模式的参与者有5个,分别是:
- Virtual Component 抽象对象的接口,可以给这些对象动态的添加职责
- Concrete Component 实例对象,可以给这个对象增加一些职责
- Virtual Decorator 维持一个指向Component对象的指针,并定义与Component接口一致的接口
- Concrete Decorator 具体向组件添加职责
- Client 用户
优点
具体实现代码
例子中Cake是抽象鸡蛋灌饼接口,OriginalCake是不加任何配料的原味鸡蛋灌饼,Decorator是抽象装饰器,EggAddCake 是给当前饼再加一个鸡蛋,SausageAddCake 是给当前饼再加一个香肠,我们在买鸡蛋灌饼时可以选择什么都不加,或加一个蛋,加多个蛋,加肠,加多个肠,同时加蛋和肠的情况,如果使用继承的方式实现上述操作可能会造成产生很多类且比较死板,比如说加蛋一个类,加肠一个类,同时加蛋和肠一个类,如果有其他配菜则会更加复杂,而使用装饰者模式则是在原有实例对象的基础上增加修饰,接下来我们通过一个实例代码来说明具体实现:
对象的接口(Component )
/****************************************************************
Author : BingLee
Date : 2019-08-07
Info :
https://blog.csdn.net/Bing_Lee (C)All rights reserved.
******************************************************************/
#ifndef CAKE_H
#define CAKE_H
#include <stdio.h>
class Cake
{
public:
virtual void Info() = 0;
virtual float Price() = 0;
};
class OriginalCake : public Cake
{
public:
OriginalCake(){}
void Info(){printf("Original test cake. ");}
float Price(){return 3.0;} //base price
};
#endif // CAKE_H
装饰器的接口(Decorator)
/****************************************************************
Author : BingLee
Date : 2019-08-07
Info :
https://blog.csdn.net/Bing_Lee (C)All rights reserved.
******************************************************************/
#ifndef DECORATOR_H
#define DECORATOR_H
#include "cake.h"
class Decorator : public Cake
{
public:
Decorator(Cake *cake = 0){
this->Init(cake);
}
void Init(Cake *cake){
if(0 == cake)
this->m_cake = new OriginalCake;
else
this->m_cake = cake;
}
virtual void Info(){m_cake->Info();}
virtual float Price(){return m_cake->Price();}
protected:
Cake *m_cake;
};
class EggAddCake : public Decorator
{
public:
EggAddCake(Cake *cake = 0){Init(cake);}
void Info(){
m_cake->Info();
printf("Add Egg. ");}
float Price(){return m_cake->Price() + 1.5;}
};
class SausageAddCake : public Decorator
{
public:
SausageAddCake(Cake *cake = 0){Init(cake);}
void Info(){
m_cake->Info();
printf("Add Sausage. ");}
float Price(){return m_cake->Price() + 2.0;}
};
#endif // DECORATOR_H
用户(Client)
#include <QCoreApplication>
#include "cake.h"
#include "decorator.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//原味鸡蛋灌饼
OriginalCake *originalCake = new OriginalCake;
originalCake->Info();
printf("\n Price %.2f\n",originalCake->Price());
//加蛋鸡蛋灌饼
EggAddCake *eggAddCake = new EggAddCake(new OriginalCake);
eggAddCake->Info();
printf("\n Price %.2f\n",eggAddCake->Price());
//加蛋加肠鸡蛋灌饼
SausageAddCake *sausageAddCake = new SausageAddCake(new EggAddCake(new OriginalCake));
sausageAddCake->Info();
printf("\n Price %.2f\n",sausageAddCake->Price());
//加肠鸡蛋灌饼
SausageAddCake *sausageAddCake1 = new SausageAddCake();
sausageAddCake1->Info();
printf("\n Price %.2f\n",sausageAddCake1->Price());
return a.exec();
}
输出结果
补充说明
如果需要专栏所有设计模式的源代码请留言留下你的联系方式,若能点赞、关注就更棒了!!!
本篇博客中的代码均已通过编译,如有Bug,请提出宝贵意见~