设计模式(七):装饰模式

装饰模式

定义

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

适用场景

普通员工有销售奖金,累计奖金,部门经理除此之外还有团队奖金;后面可能会添加环比增长奖金,同时可能针对不同的职位产生不同的奖金组合;我们要通过装饰模式为不同职位的员工添加奖金。

结构图

装饰模式

未使用是设计模式代码

class Context {
public:
    bool isMgr;
    // User user;
    // double groupsale;
};

class Bonus {
public:
    double CalcBonus(Context &ctx) {
        double bonus = 0.0;
        bonus += CalcMonthBonus(ctx);
        bonus += CalcSumBonus(ctx);
        if (ctx.isMgr) {
            bonus += CalcGroupBonus(ctx);
        }
        return bonus;
    }
private:
    double CalcMonthBonus(Context &ctx) {
        double bonus/* = */;
        return bonus;
    }
    double CalcSumBonus(Context &ctx) {
        double bonus/* = */;
        return bonus;
    }
    double CalcGroupBonus(Context &ctx) {
        double bonus/* = */;
        return bonus;
    }
};
int main() {
    Context ctx;
    // 设置 ctx
    Bonus *bonus = new Bonus;
    bonus->CalcBonus(ctx);
}

这样的设计并没有使不同的人的奖金计算分离,并且需要在类中添加很多变量(如isMgr,isBoss等)非常麻烦。

使用装饰模式

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);
}

可见装饰模式把不同职位的奖金计算分离,正如其名,向装修一样,需要什么添加什么。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值