动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式相比生成子类更加灵活。
我一直没整明白这个模式到底是怎么玩的,是弄一个虚基类,然后去拓展它的很多子类吗?我以前一直是这么认为的。
我现在依旧认为这是其中的一部分,但是后来,我又有了新的认知。
新的认知来源于我去学Python的那段时间,我开了三个Python基础入门的班,在备课的过程中,接触到了Python的装饰器。
当我看到这个名字的时候,第一反应就是装饰器模式,这,映射到C++当中,是不是就是装饰者模式呢?
我看了下去,因为我之前理解的装饰者模式是基于虚基类的,而Python可不跟你玩这个。
看了Python的装饰器,我不由自主的想到了C++的函数指针,不就是这个道理吗?搞得那么复杂,函数指针还更加的灵活多变,于是我果断选择了跟大家讲函数指针的内容。
关于函数指针和装饰器的部分可以看我的“偷偷学Python”系列最后一天:我要偷偷的学Python,然后惊呆所有人(最后一天)
函数指针方面的代码我就不展示啦,平时都在用着,我就展示一下虚基类在装饰者模式中的应用吧。
==又是线程池==,感觉这个线程池已经客串了我好多个设计模式了。不过每次的着力点都不一样,这次,是Task类。
//pthreadpool.h
#pragma once
#include <pthread.h>
#include <unistd.h>
#include <list> //据说list不安全,不安全就不安全吧,更不安全的都忍了
#include "Cond.h" //封装过的条件变量类,继承自封装的mutex锁类,所以具有锁和条件变量的双重属性
using namespace std;
这里不打注释,这次的主角是它
class Task //任务接口,每个任务必须实现的接口,以供工作线程调度任务的执行
{
public:
Task() {}
virtual ~Task() {}
virtual int run() = 0; //留给子类实现
};
typedef list<Task*> list_task; //任务队列,用于暂存等待处理的任务,等待线程唤醒时处理,提供一种缓冲机制。
class Pthread_Pool //线程池类
{
public:
Pthread_Pool(unsigned int max = 100, unsigned int min = 10, unsigned int wait = 60);
~Pthread_Pool();
void addTask(Task* task); // 往任务队列中添加新线程
看这里看这里
private:
static void* taskThread(void* arg);// 工作线程
void createThread(); // 新建一个线程
void destroyThread(); // 销毁一个线程池
unsigned int maxcount; // 最大线程数
unsigned int mincount; // 最小线程数
unsigned int count; // 当前线程池中线程数
unsigned int waitcount; // 等待线程数
unsigned int waitsec; // 等待时间
list_task taskList; //任务队列
Cond taskCond; //任务锁,线程接任务时使用
Cond cond; //线程锁,创建线程时使用
bool Stop; //线程池是否被允许运作,初始化线程池对象时置0,线程池销毁时置为1
};
具体代码太长,只需要知道工作线程会去run就可以。
调用的地方是这样的:
class DoTask : public Task
{
public:
DoTask(BtoC& send, PacketCommand1& packet);
int run();
private:
DB_command* task_db;
BtoC* m_send;
PacketCommand1 m_packet;
PacketCommand3* f_packet;
};
class BackServer
{
public:
BackServer(char* IPnum);
~BackServer() {}
int run();
private:
PacketCommand1 m_packet;
BtoC m_send;
Pthread_Pool* m_pool;
};
int BackServer::run()
{
int n = 0;
while (1)
{
n = m_send.Read_date(m_packet.getData());
m_packet.setSize(n);
DoTask* t = new DoTask(m_send, m_packet);
m_pool->addTask(t);
}
return 0;
}
如果要看完整源码的话,可以移步:
这篇详尽的介绍了我的线程池实现过程,但是没有放调用部分,调用部分就是上面这两段。
这篇放了源码和调用部分,加上了一个对象池的实现,是讲池技术的。
装饰者模式的
装饰类和被装饰类可以独立发展,不会互相耦合。
换句话说,被装饰类也不用知道装饰类,装饰类是从外部来拓展被装饰类的功能,而装饰类也不用知道自己要去装饰谁。
装饰模式是继承关系的一个替代方案,从上面可以看出来,不管装饰多少层,它还是最原始的那个东西。
装饰模式可以动态的拓展一个实现类的功能,无需多言。
缺点
多层的装饰是比较复杂的,一出现问题,你很难知道是哪一层装饰出问题。
所以尽量减少装饰的数量,降低系统复杂度。
使用场景
需要动态拓展一个类的功能,或者给一个类添加附加功能。
需要动态的给一个对象增加功能,这些功能可以动态的撤销。
需要为一批的兄弟类进行改装或加装功能,当然是首选装饰者模式。
装饰者模式是对继承的有力补充。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。