我用过的设计模式(8)-- 装饰者模式

在这里插入图片描述

装饰者模式

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

我一直没整明白这个模式到底是怎么玩的,是弄一个虚基类,然后去拓展它的很多子类吗?我以前一直是这么认为的。
我现在依旧认为这是其中的一部分,但是后来,我又有了新的认知。

新的认知来源于我去学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;
}

如果要看完整源码的话,可以移步:
【C++】勉强能看的线程池详解
这篇详尽的介绍了我的线程池实现过程,但是没有放调用部分,调用部分就是上面这两段。

我用过的设计模式(7)-- 享元模式
这篇放了源码和调用部分,加上了一个对象池的实现,是讲池技术的。


回到装饰者模式

装饰者模式的
装饰类和被装饰类可以独立发展,不会互相耦合。
换句话说,被装饰类也不用知道装饰类,装饰类是从外部来拓展被装饰类的功能,而装饰类也不用知道自己要去装饰谁。

装饰模式是继承关系的一个替代方案,从上面可以看出来,不管装饰多少层,它还是最原始的那个东西。
装饰模式可以动态的拓展一个实现类的功能,无需多言。

缺点
多层的装饰是比较复杂的,一出现问题,你很难知道是哪一层装饰出问题。
所以尽量减少装饰的数量,降低系统复杂度。

使用场景

需要动态拓展一个类的功能,或者给一个类添加附加功能。
需要动态的给一个对象增加功能,这些功能可以动态的撤销。
需要为一批的兄弟类进行改装或加装功能,当然是首选装饰者模式。

装饰者模式是对继承的有力补充。


在这里插入图片描述

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

看,未来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值