设计模式入门之装饰器模式Decorator

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //装饰模式定义:动态地给一个对象添加一些额外的职责。  
  2. //就增加功能来说,装饰模式比生成子类更为灵活  
  3. //这也提现了面向对象设计中的一条基本原则,即:尽量使用对象组合,而不是对象继承  
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //Component:组件对象的接口,可以给这些对象动态添加职责  
  2. //ConcreateComponet:具体的组件对象,实现组件对象接口,通常就是被装饰器装饰的对象,也就是可以给这个对象添加职责  
  3. //Decorator:所有装饰器的抽象父类,需要定义一个与组件接口一致的接口,并持有一个Component对象,即被装饰的对象  
  4. //在Java中比较常见的一种装饰器模式体现如下:  
  5. //new DataInputStream(new BufferedInputStream(new FileInputStream("IOtest.txt")));  
  6. //FileInputStream完成他自己的功能,然后由装饰器完成需要增加的功能  
  7. //实例:设计一个奖金系统,奖金有月奖金,累计奖金和团队奖金,根据不同的人发不同的奖金  
  8. //不使用装饰模式的实现中,各个奖金模块的耦合很严重,当有新的奖励方法时改动很多,扩展不方便  
  9. //下面是使用了装饰模式的实现方式:  
  10. //数据库模拟类,存储人员销售额,模拟,只给了一个月的销售额  
  11. public class TempDB {  
  12.     private TempDB() {  
  13.     }  
  14.     public static Map<String, Double> mapMonthSaleMoney = new HashMap<String, Double>();  
  15.     static {  
  16.         mapMonthSaleMoney.put("张三"10000.0);  
  17.         mapMonthSaleMoney.put("李四"20000.0);  
  18.         mapMonthSaleMoney.put("王五"30000.0);  
  19.     }  
  20. }  
  21. //所有奖励方法的父类,标准实现使用了抽象类  
  22. public abstract class PrizeCalculor {  
  23.     public abstract double calcPrize(String user, Date begin, Date end);  
  24. }  
  25. //需要被装饰的对象类,比如每个人每个月都会有500块的基本奖金  
  26. public class NormalPrizeCalc extends PrizeCalculor {  
  27.     public double calcPrize(String user, Date begin, Date end) {  
  28.         return 500;  
  29.     }  
  30. }  
  31. //下面是装饰器的父类  
  32. public abstract class Decorator extends PrizeCalculor{  
  33.     protected PrizeCalculor c;//被装饰的对象  
  34.     public Decorator(PrizeCalculor c) {  
  35.         this.c = c;  
  36.     }  
  37.     public double calcPrize(String user, Date begin, Date end) {  
  38.         //前后可增加功能  
  39.         return this.c.calcPrize(user, begin, end);//默认直接转调被装饰对象的方法  
  40.     }  
  41. }  
  42. //月奖金装饰器类  
  43. public class MonthPrizeDecorator extends Decorator{  
  44.     public MonthPrizeDecorator(PrizeCalculor c) {  
  45.         super(c);  
  46.     }  
  47.     public double calcPrize(String user, Date begin, Date end) {  
  48.         double money = super.calcPrize(user, begin, end);//先获得被装饰对象的奖金  
  49.         double prize = TempDB.mapMonthSaleMoney.get(user)*0.03;//计算月奖金  
  50.         System.out.println(user+"当月业务奖金"+prize);  
  51.         return money+prize;//返回被装饰对象的总奖金  
  52.     }  
  53. }  
  54. //累计奖金装饰器类,作用同上  
  55. public class SumPrizeDecorator extends Decorator{  
  56.     public SumPrizeDecorator(PrizeCalculor c) {  
  57.         super(c);  
  58.     }  
  59.     public double calcPrize(String user, Date begin, Date end) {  
  60.         double money = super.calcPrize(user, begin, end);  
  61.         double prize = 100000*0.001;//假设所有人的累计销售额都是100000  
  62.         System.out.println(user+"累计奖金"+prize);  
  63.         return money+prize;  
  64.     }  
  65. }  
  66. //团队奖金装饰器类,只有项目经理才有  
  67. public class GroupPrizeDecorator extends Decorator{  
  68.     public GroupPrizeDecorator(PrizeCalculor c) {  
  69.         super(c);  
  70.     }  
  71.     public double calcPrize(String user, Date begin, Date end) {  
  72.         double money = super.calcPrize(user, begin, end);  
  73.         double group = 0.0;  
  74.         for(double d : TempDB.mapMonthSaleMoney.values()) {  
  75.             group += d;  
  76.         }  
  77.         double prize = group * 0.01;  
  78.         System.out.println(user+"当月团队业务奖金"+prize);  
  79.         return money + prize;  
  80.     }  
  81. }  
  82. //客户端测试类  
  83. public class Client {  
  84.     public static void main(String[] args) {  
  85.         PrizeCalculor calc = new NormalPrizeCalc();  
  86.         Decorator d1 = new MonthPrizeDecorator(calc);  
  87.         Decorator d2 = new SumPrizeDecorator(d1);  
  88.         //把被装饰对象进行组合,calc对象经d1装饰,然后d1对象经d2装饰  
  89.         double zs = d2.calcPrize("张三"nullnull);  
  90.         System.out.println(zs);  
  91.         double ls = d2.calcPrize("李四"nullnull);  
  92.         System.out.println(ls);  
  93.         Decorator d3 = new GroupPrizeDecorator(d2);  
  94.         //项目经理,d2对象再经d3对象装饰  
  95.         double ww = d3.calcPrize("王五"nullnull);  
  96.         System.out.println(ww);  
  97.     }  
  98. }  
  99. //装饰模式的本质:动态组合  
  100. //装饰器模式优点:比继承更加灵活,更容复用功能,简化高层定义  
  101. //装饰器模式缺点:会产生很多细粒度对象  
  102. //注意:各个装饰器之间最好是完全独立的功能,不要有依赖,这样在进行装饰组合的时候,才没有先后顺序的限制,也就是先装饰谁和后装饰谁都是一样的,否则会大大降低装饰漆组合的灵活性  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值