装饰者设计模式

1、定义

动态地给一个对象增加一些额外的职责。就增加功能而言,装饰器模式比生产子类更为灵活。—— 《设计模式》GoF

2、代码实现

代码背景:普通员工有销售奖金,累计奖金,部门经理除此之外还有团队奖金;后面可能会添加环比增长奖金,同时可能针对不同的职位产生不同的奖金组合;

#include <iostream>
using namespace std;

//封装被计算奖金的人员信息
class Context {
public:
    bool isMgr;
    // User user;
    // double groupsale;
};

// 试着从职责出发,将职责抽象出来
class CalcBonus {    
public:
    CalcBonus(CalcBonus * c = nullptr) : cc(c) {}
    virtual double Calc(Context &ctx) {
        return 0.0; // 基本工资
    }
    virtual ~CalcBonus() {}

protected:
    CalcBonus* cc;
};

//月度奖金
class CalcMonthBonus : public CalcBonus {
public:
    CalcMonthBonus(CalcBonus * c) : CalcBonus(c) {}
    virtual double Calc(Context &ctx) {
        double mbonus /*= 计算流程忽略*/; 
        return mbonus + cc->Calc(ctx);
    }
};

//季度奖金
class CalcSumBonus : public CalcBonus {
public:
    CalcSumBonus(CalcBonus * c) : CalcBonus(c) {}
    virtual double Calc(Context &ctx) {
        double sbonus /*= 计算流程忽略*/; 
        return sbonus + cc->Calc(ctx);
    }
};

//小组奖金
class CalcGroupBonus : public CalcBonus {
public:
    CalcGroupBonus(CalcBonus * c) : CalcBonus(c) {}
    virtual double Calc(Context &ctx) {
        double gbnonus /*= 计算流程忽略*/; 
        return gbnonus + cc->Calc(ctx);
    }
};

//环比奖金
class CalcCycleBonus : public CalcBonus {
public:
    CalcCycleBonus(CalcBonus * c) : CalcBonus(c) {}
    virtual double Calc(Context &ctx) {
        double gbnonus /*= 计算流程忽略*/; 
        return gbnonus + cc->Calc(ctx);
    }
};

int main() {
    // 1. 普通员工
    Context ctx1;
    //就是在每个奖金的基础上进行叠加(叠加没有先后顺序)
    CalcBonus *base = new CalcBonus();
    CalcBonus *cb1 = new CalcSumBonus(base);
    CalcBonus *cb2 = new CalcMonthBonus(cb1);
    cb2->Calc(ctx1);
    
    // 2. 部门经理
    Context ctx2;
    CalcBonus *cb3 = new CalcGroupBonus(cb2);
    cb3->Calc(ctx2);
}

代码分析:

  1. 实现起来和责任链有点相似,装饰者模式就像一层套一层的感觉,不需要有顺序,只要该套的套完了就行

    • 责任链:强调顺序,且可以在某个位置打断

    • 装饰者:强调结果,顺序无所谓

  2. 责任链是第一环调用处理函数,这里是装饰的最后一个调用处理函数

3、要点

  • 装饰者模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能

  • 装饰者模式把一系列复杂的功能分散到每个装饰器当中,一般一个装饰器只实现一个功能,实现复用装饰器的功能

  • 场景:给一个主体叠加多层需求的场景

    • 给某个员工计算奖金
    • 给游戏人物搭配衣服
    • 给一辆汽车选配置

4、本质

  • 动态组合—对一个对象进行多重自定义装饰,不考虑顺序,只考虑装饰结果

5、结构图

装饰者设计模式

上一篇:【实现】表单控件的UI布局,实现方式


下一篇:5.alc()的运算规则