设计模式——装饰器模式
文章目录
- 一、基本知识
- 1.定义
- 2.背景示例
- 3.要点
- 二、结构图
- 三、实例说明
- 1.普通代码
- 2.装饰器模式代码
一、基本知识
在我第一次接触装饰器模式的时候,将它和责任链模式分不开,但是事实上它们是有区别的。
1.定义
动态地给一个对象增加一些额外的职责。就增加功能而言,装饰器模式比生产子类更为灵活。
2.背景示例
普通员工有销售奖金,累计奖金,部门经理除此之外还有团队奖金;后面可能会添加环比增长奖金,同时可能针对不同的职位产生不同的奖金组合。
3.要点
①通过采用组合而非继承的手法, 装饰器模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。 避免了使用继承带来的“灵活性差”和“多子类衍生问题”。
②不是解决“多子类衍生问题”问题,而是解决“父类在多个方向上的扩展功能”问题。
③装饰器模式把一系列复杂的功能分散到每个装饰器当中,一般一个装饰器只实现一个功能,实现复用装饰器的功能。
二、结构图
对于本人来说,先看结构图的话,看不懂,都是先看示例代码,回头来再看结构图才看得懂。
三、实例说明
1.普通代码
#include<iostream>
#include<string>
using namespace std;// 普通员工有销售奖金,累计奖金,部门经理除此之外还有团队奖金;后面可能会添加环比增长奖金,同时可能产生不同的奖金组合;
// 销售奖金 = 当月销售额 * 4%
// 累计奖金 = 总的回款额 * 2%
// 部门奖金 = 团队销售额 * 1%
// 环比奖金 = (当月销售额-上月销售额) * 1%
// 销售后面的参数可能会调整
class Context {public:bool isMgr;string name;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;// 设置 ctxBonus* bonus = new Bonus;bonus->CalcBonus(ctx);
}
2.装饰器模式代码
#include <iostream>
#include <string>
// 普通员工有销售奖金,累计奖金,部门经理除此之外还有团队奖金;后面可能会添加环比增长奖金,同时可能产生不同的奖金组合;
// 销售奖金 = 当月销售额 * 4%
// 累计奖金 = 总的回款额 * 0.2%
// 部门奖金 = 团队销售额 * 1%
// 环比奖金 = (当月销售额-上月销售额) * 1%
// 销售后面的参数可能会调整
using namespace std;
class Context {public:bool isMgr;string name;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;ctx1.isMgr = false;CalcBonus *base = new CalcBonus();CalcBonus *cb1 = new CalcSumBonus(base);CalcBonus *cb2 = new CalcMonthBonus(cb1);cb2->Calc(ctx1);//普通员工奖金只求销售奖金和部门奖金// 2. 部门经理Context ctx2;ctx2.isMgr = true;CalcBonus *cb3 = new CalcGroupBonus(cb2);cb3->Calc(ctx2);//部门奖金求销售、累计、部门奖金(环比奖金暂时没有设置)
}
可以看见,装饰器和责任链最大的区别是装饰器模式是最主要的是组合手法。而责任链是继承,然后每个子类的实例之间通过链表的方式低度耦合。装饰器之所以采用组合,是因为子类并不只是其中一个子类符合条件进行操作,而是多个子类都要操作,比如奖金,是通过多个子类求出来的。
而责任链模式通常是某个子类来解决这个事情,而链表是通常按照一定的先后顺序将子类低度耦合起来,有事件要处理时,通过链表遍历这个链表上的类,找到适合处理这个事情的类,这个往往是一个类就可以处理完。
当然,其实大部分可以用装饰器模式的很可能也可以用责任链模式,因为责任链模式只是往往一个事件只需要一个类处理,但是也可以是多个类都要处理,但是通过执行先后顺序将类用链表连接起来,就像是一个工厂的流水线一样。
设计模式——装饰器模式相关推荐
- Python设计模式-装饰器模式
Python设计模式-装饰器模式 代码基于3.5.2,代码如下; #coding:utf-8 #装饰器模式class Beverage():name = ""price = 0.0 ...
- Go 设计模式 - 装饰器模式
装饰模式使用对象组合的方式动态改变或增加对象行为.Go语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式.使用匿名组合,在装饰器中不必显式定义转调原对象方法. 设计模式 装饰器模式 装饰器模式主要 ...
- Spring设计模式(装饰器模式)
Spring设计模式(装饰器模式) 模式的定义: 装饰者模式定义: 动态地为一个对象添加一些额外的职责,若要扩展一个对象的功能,装饰者提供了比继承更有弹性的替代方案. 模式的结构图 : 模式包含角 ...
- Java设计模式-装饰器模式 理论代码相结合
继Java设计模式适配器模式后的装饰器模式来啦,让我们一起看看吧. 会了就当复习丫,不会来一起来看看吧. 很喜欢一句话:"八小时内谋生活,八小时外谋发展". 如果你也喜欢,让我们一 ...
- 设计模式--装饰器模式
装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装.简单来说,装饰器模式就是 ...
- PHP设计模式——装饰器模式
声明:本系列博客参考资料<大话设计模式>,作者程杰. 装饰器模式又叫装饰者模式.装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装 ...
- 设计模式-装饰器模式 C++
一.简介 1.什么是装饰器模式 装饰器模式是结构型设计模式. 装饰器是现有类的一个包装,可以在不修改现有类且不增加子类的情况下扩展现有类. [注]可以实现向一个现有对象添加新的功能,同时又不改变其结构 ...
- 设计模式---装饰器模式(C++实现)
装饰器模式(Decorator Pattern)允许向一个现有对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原 ...
- C++设计模式 装饰器模式
文章目录 1. 先验知识 2. 装饰器模式相关概念 3. 装饰器模式的应用 3.1 应用1: 给形状添加新的特征 不同形状加红 3.2 应用2: 给一个人穿不同的衣服 a 直接person类, 增加穿 ...
- 白话设计模式-装饰器模式的使用和意义
装饰器模式展示 在学习设计模式的过程中,将自己对于设计模式的理解,以最简单,最白话的方式,分享给大家.个人觉得,对于设计模式的理解,需要将他从最抽象的理论里,真实的代入到实际的业务场景中,将会有最深刻 ...
最新文章
- google gn构建系统的介绍
- Mysql 源码安装
- 使用JDBC进行批处理
- [YTU]_2435 ( C++ 习题 输出日期时间--友元函数)
- Silverlight和WCF交互式的实战项目(更新完毕)
- IntelliJ IDEA for Mac在MacOS模式下的导航快捷键(Navigation Shortcut)
- java在什么环境变量_Java-环境变量
- 普通地图的六大要素_地理知识点总结之地图基本要素
- 高考学文的能报计算机吗,高考志愿填报时,文科生能申报计算机类相关专业吗?...
- CentOS install btsync
- 基于MATLAB的线性规划
- python中的snip用法_mac版截图软件Snip详细使用教程及常见问题
- 视频解码芯片GM7150BC功能CVBS转BT656/601低功耗替代TVP5150
- 学科分类号 计算机技术,学科分类号 0806.DOC
- 微信小程序实现图片翻转效果
- IGame游戏公司的故事
- 济南市全国计算机二级,山东省济南市2019年下半年全国计算机等级考试报名时间...
- 天气预报php xml接口,php调用天气预报接口
- 自动适配跳转电脑PC端和手机WAP端
- 计算机网络 路由器的端口ip,给路由器的一个接口上配置两个IP地址
热门文章
- 用Unity3D实现简单的井字棋小游戏
- 各种拿webshell
- [Python爬虫] 在Windows下安装PIP+Phantomjs+Selenium
- App设计灵感之十二组精美的房产App设计案例
- 树莓派搭建Django服务器通过远程访问
- 2017第八届蓝桥杯C/C++ B组省赛 —— 第一题:购物单
- 第六章 定积分的应用 —— 第一节 定积分的元素法
- 【ARM】ARM汇编程序设计(四) 选择结构
- 【Linux】一步一步学Linux——rmdir命令(22)
- mongodb 输出数组字段_JMeter之Groovy对MongoDB操作