zl程序教程

您现在的位置是:首页 >  后端

当前栏目

C++设计模式详解之装饰者模式解析

C++模式设计模式 详解 解析 装饰
2023-09-14 09:05:11 时间

装饰者模式的概念

装饰者模式指的是动态的将责任附加到对象上,想要扩展其功能,装饰者提供有别于继承的另一种选择。(参考《Head First 设计模式》)

个人理解:装饰者就是一种类包类 就是在构造函数里面,添加类作为参数。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

装饰者模式原则

封装变化

多用组合,少用继承

针对接口编程,不针对实质编程

为交互对象的松耦合设计而努力

对扩展开放,对修改关闭

装饰者模式实例

例如男生和女生可以被认为是被装饰者,洗澡和吃饭可以理解为装饰行为, 就是装饰者模式,在我看来最大的好处 就是行为与行为者可以分开,毕竟好扩展。 就是可以今天是男生洗澡,女生吃饭, 也可以是女生洗澡 男生吃饭。 接下来来实现这一行为

首先是基准类的头文件,男生女生都是人 所以以人作为基准类的声明如下,定义了两个纯虚函数,一个是人的类别,一个是人的行为。

//所有的基类 人
class People
{
public:
  virtual void personType()= 0; //人的类型
  virtual void personAction() = 0; //人的活动
};

接下来是被装饰者男生女生各自的类的行为和活动

头文件:

//被装饰者 :男生
class Boy:public People
{
public:
  //继承人的两个方法
  void personType();
  void personAction();
};

//被装饰者:女生
class Girl:public People
{
public:
  void personType();
  void personAction();
};

各自类的实现如下:

//实现相关类
//男生类
void Boy::personType()
{
  cout << "Boy:" << endl;
}

void Boy::personAction()
{
  cout << "Boy要做的事情是" << endl;
}

//女生类
void Girl::personType()
{
  cout << "Girl:" << endl;
}

void Girl::personAction()
{
  cout << "Girl要做的事情是" << endl;
}

接下来是定义一个装饰行为的基类,也是继承于人,这个是装饰者模式必须要做的一个东西。

装饰者基类的声明

//装饰者行为基类:继承于人
class PersonConduct:public People
{
public:
  PersonConduct(People *cur_people);
    
  void personType();
  void personAction();

protected:
  People *m_pPeople;
};

接下来是两个吃饭和洗澡行为的声明

//装饰行为:吃饭
class Eat:public PersonConduct
{
public:
  Eat(People *cur_people):PersonConduct(cur_people){}
  void personType();
  void personAction();
};

//装饰行为:洗澡
class Bash:public PersonConduct
{
public:
  Bash(People *cur_people):PersonConduct(cur_people){}
  void personType();
  void personAction();
};

其中一个主要的点,需要构造函数中添加 基类的指针,以实现能够调用被装饰者的动作。

具体装饰行为类实现的代码如下:

//装饰行为基类
PersonConduct::PersonConduct(People *cur_people)
{
  m_pPeople= cur_people;
}
void PersonConduct::personType()
{
  m_pPeople->personType();
}

void PersonConduct::personAction()
{
  m_pPeople->personAction();
}

//装饰行为:基类
void Eat::personType()
{
  m_pPeople->personType();
  cout << "肚子很饿" << endl;
  return;
}

void Eat::personAction()
{
  m_pPeople->personAction();
  cout << "正在吃饭" << endl;
}

//装饰行为:洗澡类

void Bash::personType()
{
  m_pPeople->personType();
  cout << "身上有味道" << endl;
}

void Bash::personAction()
{
  m_pPeople->personAction();
  cout << "正在洗澡" << endl;
}

测试是否实现装饰者模式的代码如下:

People * cur_boy = new Boy();
  People *  cur_girl = new Girl();

  PersonConduct * cur_eat_action = new Eat(cur_girl); //绑定女孩
  cur_eat_action->personType();
  cur_eat_action->personAction();

  PersonConduct * cur_bash_action = new Bash(cur_boy);//绑定男孩
  cur_bash_action->personType();
  cur_bash_action->personAction();

执行结果:

 

可以看出,完美的实现了装饰者行为,当然,代码还有不完善的地方 在于没有释放内存最后。都要delete 指针。但是希望可以帮助大家很好的理解装饰者模式。

装饰者模式的注意事项

显然 装饰者模式的好处显而易见,就是对象和操作分离,可以这么理解。吃饭不是只有男生能吃,也不是只有女生能吃,如果使用继承的话,需要写男生继承一次,女生继承一次,如果有很多行为的话,显然代码量巨大,所以使用装饰者模式可以很好的解决这一问题,当然,如果当对象是单一的情况下,使用装饰者模式就显得很麻烦了,因为还要写装饰者基类啥的,每个行为一个类 很麻烦,希望大家可以活学活用最好。这也是设计模式的意义所在。

实例完整代码

头文件:

#include "stdafx.h"

using namespace std;

//所有的基类 人
class People
{
public:
    virtual void personType()= 0; //人的类型
    virtual void personAction() = 0; //人的活动
};

//被装饰者 :男生
class Boy:public People
{
public:
    //继承人的两个方法
    void personType();
    void personAction();
};

//被装饰者:女生
class Girl:public People
{
public:
    void personType();
    void personAction();
};

//装饰者行为基类:继承于人
class PersonConduct:public People
{
public:
    PersonConduct(People *cur_people);
    
    void personType();
    void personAction();

protected:
    People *m_pPeople;
};

//装饰行为:吃饭
class Eat:public PersonConduct
{
public:
    Eat(People *cur_people):PersonConduct(cur_people){}
    void personType();
    void personAction();
};

//装饰行为:洗澡
class Bash:public PersonConduct
{
public:
    Bash(People *cur_people):PersonConduct(cur_people){}
    void personType();
    void personAction();
};

实现文件

// DecorationMode.cpp : 定义控制台应用程序的入口点。
// 装饰者模式

#include "stdafx.h"
#include "DecorationMode.h"

using namespace std;
//实现相关类
//男生类
void Boy::personType()
{
  cout << "Boy:" << endl;
}

void Boy::personAction()
{
  cout << "Boy要做的事情是" << endl;
}

//女生类
void Girl::personType()
{
  cout << "Girl:" << endl;
}

void Girl::personAction()
{
  cout << "Girl要做的事情是" << endl;
}

//装饰行为基类
PersonConduct::PersonConduct(People *cur_people)
{
  m_pPeople= cur_people;
}
void PersonConduct::personType()
{
  m_pPeople->personType();
}

void PersonConduct::personAction()
{
  m_pPeople->personAction();
}

//装饰行为:基类
void Eat::personType()
{
  m_pPeople->personType();
  cout << "肚子很饿" << endl;
  return;
}

void Eat::personAction()
{
  m_pPeople->personAction();
  cout << "正在吃饭" << endl;
}

//装饰行为:洗澡类

void Bash::personType()
{
  m_pPeople->personType();
  cout << "身上有味道" << endl;
}

void Bash::personAction()
{
  m_pPeople->personAction();
  cout << "正在洗澡" << endl;
}


int _tmain(int argc, _TCHAR* argv[])
{
  People * cur_boy = new Boy();
  People *  cur_girl = new Girl();

  PersonConduct * cur_eat_action = new Eat(cur_girl); //绑定女孩
  cur_eat_action->personType();
  cur_eat_action->personAction();

  PersonConduct * cur_bash_action = new Bash(cur_boy);//绑定男孩
  cur_bash_action->personType();
  cur_bash_action->personAction();

  return 0;
}

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓