Decorator 装饰器模式 -动态组合
为什么80%的码农都做不了架构师?>>>
一:业务场景
奖金计算,每个部门,有不同的计算方法,且每个部门有不同类型的奖金项;而且每年或每隔几个季度奖金算法都要重新实现下。
这个应用场景应该比较合适了。
我先列出几个计算公式:
每人当月的业务奖金 = 当月销售额 * 3%;
每人累计奖金 = 总的回款额*0.1%;
团队奖金 = 团队销售总额*1%;(只有经理才有哦)
二:不用设计模式,我们程序如下实现:
这里演示代码,就不用数据库了
/*** 在内存中模拟DB,准备好测试数据* @author dy* @since 2016-08-11 & JDK 1.8.0_91*/ public class TempDB {/*** 记录每人每月销售额,这里为了演示,只有人员,没有月份* 这里演示 假设每人每月销售业务金额都是相同的哈*/public static Map<String,Double> mapMonthSaleMoney = new HashMap<>();public static Map<String,String> saleManager = new HashMap<>();static {mapMonthSaleMoney.put("杨过", 10000.00);mapMonthSaleMoney.put("令狐冲", 20000.00);mapMonthSaleMoney.put("韦小宝", 30000.00);mapMonthSaleMoney.put("dy", 10000.00);saleManager.put("经理", "dy");} }
接下来写不同奖金计算方法
/*** 计算某人当月的业务奖金** @param user* @param month* @return*/ private double monthPrize(String user, int month) {//当月业务奖金 = 业务额*3%double prize = TempDB.mapMonthSaleMoney.get(user) * 0.03;System.out.println(user + " " + month + "月份业务奖金:" + prize);return prize; }/*** 计算某人当月累计奖金** @param user* @param month* @return*/ private double sumPrize(String user, int month) {//这里演示 假设每人每月销售业务金额都是相同的哈//累计业务奖金 = 累计业务金额*0.1%double prize = TempDB.mapMonthSaleMoney.get(user) * 0.001;System.out.println(user + " " +month+"月份累计奖金:"+prize);return prize; }/*** 是否是业务经理** @param user* @return*/ private boolean isManager(String user) {return TempDB.saleManager.get("经理").equals(user); }/*** 计算当月团队奖金** @param user* @param month* @return*/ private double groupPrize(String user, int month) {if (!isManager(user)){return 0;}//团队奖金 = 团队总业务额 * 1%double prize = 0.00;for (double amount : TempDB.mapMonthSaleMoney.values()) {prize += amount;}prize = prize * 0.01;System.out.println(user + " " +month+"月份团队奖金:"+prize);return prize; }
ok,我们开始计算奖金吧
/*** 计算奖金* @param month* @return*/ public void calcPrize(String user,int month) {double monthPrize = this.monthPrize(user, month);double sumPrize = this.sumPrize(user, month);double groupPrize =groupPrize(user, month);System.out.println(user + " " +month+"月份应得奖金:"+(monthPrize+sumPrize+groupPrize)+"==>>");}
客户端测试
public class Client {public static void main(String[] args) {Prize prize = new Prize();for (String user:TempDB.mapMonthSaleMoney.keySet()){prize.calcPrize(user,3);}} }
测试结果:
以上代码有何问题??
如果我们计算奖金算法变了呢??如果我们要增加新的奖金项? 如果我们要移除累计奖金项呢??等等
我们是不是需要频繁改动代码呢?作为一个老鸟程序员,我们要求程序要更加灵活、支持可扩展!
如果做到呢?
我们把问题抽象下,假如有个奖金对象,可以支持灵活的增加或减少不同的奖金项,就意味着奖金对象的功能可以动态组合,这样是不是会更好些呢?
三:使用装饰模式,
动态地为一个对象增加或减少一些职责。就增加职责来说,比子类更加灵活。
如下是装饰模式结构说明:
ok,让我们利用装饰模式,重新实现计算奖金吧!
/*** 计算金额的组件接口* @author dy* @since 2016-08-11 & JDK 1.8.0_91*/ public abstract class Component {/*** 计算奖金* @param month*/public abstract double calcPrize(String user,int month); }
/*** 基本的实现类,默认实现,也是被装饰的对象* @author dy* @since 2016-08-11 & JDK 1.8.0_91*/ public class ConcreteComponent extends Component {@Overridepublic double calcPrize(String user,int month) {System.out.println("默认没有奖金!");return 0;} }
/*** 装饰器* 需要和被装饰的对象实现同样的接口* @author dy* @since 2016-08-11 & JDK 1.8.0_91*/ public abstract class Decorator extends Component {/*** 持有被装饰的对象*/protected Component component;public Decorator(Component component) {this.component = component;}@Overridepublic double calcPrize(String user,int month) {double prize = component.calcPrize(user,month);//转调组件对象的方法return prize;} }
/*** 装饰器对象 ,计算当月业务奖金** @author dy* @since 2016-08-11 & JDK 1.8.0_91*/ public class MonthPrizeDecorator extends Decorator {public MonthPrizeDecorator(Component component) {super(component);}@Overridepublic double calcPrize(String user, int month) {double money = super.calcPrize(user, month);double monthPrize = TempDB.mapMonthSaleMoney.get(user) * 0.03;System.out.println(user + " " + month + "月份业务奖金:" + (monthPrize) + "==>>");return monthPrize + money;} }
/*** 装饰器对象 ,计算累计奖金** @author dy* @since 2016-08-11 & JDK 1.8.0_91*/ public class SumPrizeDecorator extends Decorator {public SumPrizeDecorator(Component component) {super(component);}@Overridepublic double calcPrize(String user, int month) {double money = super.calcPrize(user, month);double sumPrize = TempDB.mapMonthSaleMoney.get(user) * 0.001;System.out.println(user + " " + month + "月份累计奖金:" + (sumPrize) + "==>>");return sumPrize + money;} }
/*** 装饰器对象 ,计算累计奖金* @author dy* @since 2016-08-11 & JDK 1.8.0_91*/ public class GroupPrizeDecorator extends Decorator {public GroupPrizeDecorator(Component component) {super(component);}@Overridepublic double calcPrize(String user,int month) {double money = super.calcPrize(user,month);if (!isManager(user)){return money;}double totalPrize = 0.00;//团队奖金 = 团队总业务额 * 1%double prize = 0.00;for (double amount : TempDB.mapMonthSaleMoney.values()) {prize += amount;}prize = prize*0.01;System.out.println(user + " " +month+"月份团队奖金:"+(prize)+"==>>");return money + prize;}private boolean isManager(String user) {return TempDB.saleManager.get("经理").equals(user);} }
以上将不同计算奖金方式拆解成不同组件,需要哪些奖金计算,自动装置就可以了,让我们来试试吧!
public class Client {public static void main(String[] args) {for (String user : TempDB.mapMonthSaleMoney.keySet()) {//创建基本奖金对象Component component = new ConcreteComponent();/*** 对基本奖金进行装饰,这里要组合各个装饰*/Decorator decorator1 = new MonthPrizeDecorator(component);Decorator decorator2 = new SumPrizeDecorator(decorator1);Decorator decorator3 = new GroupPrizeDecorator(decorator1);//这里只需要用最后组合好的对象调用业务方法即可double prize = decorator3.calcPrize(user, 3);System.out.println(user + " " +3+"月份应得奖金:"+prize+"==>>");}} }
运行结果,和我们原始代码结果一模一样,但本质上却更加灵活了
以上代码调用示例
转载于:https://my.oschina.net/dyyweb/blog/731318
Decorator 装饰器模式 -动态组合相关推荐
- Java —— Decorator 装饰器模式
文章目录 Java -- Decorator 装饰器模式 简介 用处 简单例子 结构 代码 涉及角色 相关的设计模式 应用实例 优点 缺点 使用场景 注意事项 代码 Java -- Decorator ...
- 6中结构型设计模式的对比理解(Composite组合模式,Proxy代理模式,Flyweight享元模式,Facade门面模式,Bridge桥接模式,Decorator装饰器模式)
结构型模式 结构型模式用来组装 类和对象,以获得更大的结构. 结构型类模式,通过继承机制来组合接口或类.简单的例子就是多重继承,最后一个类拥有所有父类的性质.这个模式有助于独立开发一个协同类.另一个例 ...
- 装饰器模式与java.io包
为什么80%的码农都做不了架构师?>>> Decorator设计模式是典型的结构型模式(在GOF的那本模式的Bible中将模式分为:1.创建型模式:2.结构型模式:3.行为模式 ...
- C++设计模式----装饰器模式
文章目录 装饰器模式使用场景 引入装饰器模式 另一个装饰器模式的例子---计算水果饮料的价格 装饰器模式的定义 装饰器模式使用场景 我们的游戏中一般都会有UI(用户接口)界面,比如背包中的格子: 或者 ...
- 装饰器模式和适配器模式
装饰器模式 装饰器模式(Decorator )允许向一个现有的对象添加新的增强功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 一般的,我们为了扩展一个类经常使 ...
- 聊聊在Vue项目中使用Decorator装饰器
戳蓝字" Web前端严选 " 关注我们哦 ! 前言 初衷: 前几天我在公司其它Vue项目中,发现了是用Decorator装饰器模式开发的,看起来整体代码还不错,于是就做了一下笔记分 ...
- 单一职责模式之装饰器模式
装饰器模式 动态地给一个对象添加一些额外的职责.就增加功能来说,装饰器模式比生成子类更为灵活. 装饰器的优点 装饰类和被装饰类可以独立发展,而不会相互耦合. 装饰器模式是继承关系的一个替代方案. 装饰 ...
- python中的装饰器、装饰器模式_python 设计模式之装饰器模式 Decorator Pattern
#写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...
- 装饰器模式(Decorator Pattern)
23种设计模式完整教程 介绍 装饰者模式(Decorator Pattern)是指在不改变原有对象的基础之上,将功能附加到对 象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式 ...
最新文章
- #1413 : Rikka with String 后缀自动机 + 二级差分
- TCP协议的3次握手和4次挥手
- 多功能节点连线绘图控件Nevron Diagram for .NET使用方法及下载地址
- 很遗憾,总对工作挑挑拣拣的家伙,一般结局都不会太好
- 属性面板 脚本_3.1 创建和使用脚本
- 利用fiddler给android模拟器抓包
- java实现文件压缩与解压
- python和java哪个好-Python和Java哪个薪资更高、远景更好?
- 计算机组成原理第五版第四章课后答案,计算机组成原理第4章习题参考答案
- 【数据分析软件】【Weka】第一课:超easy安装教程
- 使用电脑小技巧70个
- 五脏六腑在脸上的反射区图片_人体五大反射区的有图详解。
- 移动NB的APN知识汇总(及时补充)
- C# 模拟PCM数据并创建WAV文件
- MySQL学习宝典之最全的常用语法语句
- python class调用_python class中的方法调用
- bzoj1022 约翰的游戏 反SG-博弈
- 2017届南京富士通南大软件校招软件工程师面经
- 老铁们来来来,实战STM32
- dhcp服务器响应慢,开机显示DHCP,速度很慢,为什么