装饰者模式

转载 2016年10月17日 09:51:16

装饰模式定义:装饰模式动态的将责任附加到对象上,若要扩展功能,装饰模式提供了比继承更有弹性的替代方案

看下下面的例子,总共有两种咖啡:Decaf、Espresso,另有两种调味品:Mocha、Whip(3种设计的主要差别在于抽象方式不同)

设计一:

即使添加在多的调味品,咖啡依然是咖啡,在抽象的过程中并没有考虑咖啡和调味品之间的关系

当咖啡和调味品的种类很多时,将会产生大量的类,如果一种咖啡的价格发生变动,需要找到所有相关的类逐一修改

设计二:

将调味品作为Coffee类的属性,比起设计一,类的数量大大减少,相应的,程序结构也更加清晰

  1. public class Coffee {  
  2.     private boolean mocha;  
  3.     private boolean whip;  
  4.       
  5.     public double cost(){  
  6.         double price = 0d;  
  7.         if(mocha){  
  8.             price += 0.5;  
  9.         }  
  10.         if(whip){  
  11.             price += 0.1;  
  12.         }  
  13.         return price;  
  14.     }  
  15.       
  16.     public void addMocha(){  
  17.         this.mocha = true;  
  18.     }  
  19.       
  20.     public void addWhip(){  
  21.         this.whip = true;  
  22.     }  
  23. }  
  1. public class Decaf extends Coffee{  
  2.     public double cost(){  
  3.         double price = super.cost();  
  4.         price += 2.0;  
  5.         return price;  
  6.     }  
  7. }  
  1. public class Espresso extends Coffee {  
  2.     public double cost(){  
  3.         double price = super.cost();  
  4.         price += 2.5;  
  5.         return price;  
  6.     }  
  7. }  

测试一下:

  1. public class Test {  
  2.     public static void main(String[] args) {  
  3.         Coffee coffee = new Decaf();  
  4.         coffee.addMocha();  
  5.         coffee.addWhip();  
  6.         //2.6  
  7.         System.out.println(coffee.cost());  
  8.     }  
  9. }  

考虑到下面几个问题,设计二有明显的不足:

1,如果调味品的种类较多,Coffee类将会变得相当庞大,难以维护

2,无法处理顾客希望添加双倍的Mocha的场景

3,添加一种新的咖啡IceCoffee,从逻辑上来说IceCoffee是不能加Mocha的,但是由于IceCoffee类继承自Coffee类,IceCoffee类依然从父类继承了addMocha()方法,这就需要在IceCoffee类中重写一个空的addMocha()方法,并且当使用IceCoffee类时,不能够面向Coffee类编程,以避免错误的调用父类方法

设计三--装饰器模式:

装饰模式分为3个部分:

1,抽象组件 -- 对应Coffee类

2,具体组件 -- 对应具体的咖啡,如:Decaf,Espresso

3,装饰者 -- 对应调味品,如:Mocha,Whip

装饰模式有3个特点:

1,具体组件和装饰者都继承自抽象组件(Decaf、Espresson、Mocha和Whip都继承自Coffee),并且装饰者持有抽象组件的引用

2,可以使用装饰者组合具体组件创造出新的类(Mocha组合Decaf创造出MochaDecaf)

3,过程2可以重复,直到创造出需要的类

使用装饰模式,想要获得一个WhipDoubleMochaEspresso是很容易的:

  1. public interface Coffee {  
  2.     public double cost();  
  3. }  
  1. public class Espresso implements Coffee {  
  2.     public double cost(){  
  3.         return 2.5;  
  4.     }  
  5. }  
  1. public class Dressing implements Coffee {  
  2.     private Coffee coffee;  
  3.       
  4.     public Dressing(Coffee coffee){  
  5.         this.coffee = coffee;  
  6.     }  
  7.       
  8.     public double cost(){  
  9.         return coffee.cost();  
  10.     }  
  11. }  
  1. public class Whip extends Dressing {  
  2.     public Whip(Coffee coffee){  
  3.         super(coffee);  
  4.     }  
  5.       
  6.     public double cost(){  
  7.         return super.cost() + 0.1;  
  8.     }  
  9. }  
  1. public class Mocha extends Dressing {  
  2.     public Mocha(Coffee coffee){  
  3.         super(coffee);  
  4.     }  
  5.       
  6.     public double cost(){  
  7.         return super.cost() + 0.5;  
  8.     }  
  9. }  

测试一下:

  1. public class Test {  
  2.     public static void main(String[] args) {  
  3.         Coffee coffee = new Espresso();  
  4.         coffee = new Mocha(coffee);  
  5.         coffee = new Mocha(coffee);  
  6.         coffee = new Whip(coffee);  
  7.         //3.6(2.5 + 0.5 + 0.5 + 0.1)  
  8.         System.out.println(coffee.cost());  
  9.     }  
  10. }  

当然Decorator类中可以重写父类的方法,也可以扩展自己需要的方法

 

装饰模式的缺点:

1,装饰模式虽然扩展性较高,但是没有设计二简洁,类的数量略多(但肯定比设计一少很多),如何取舍可扩展性和简洁性是个问题,有所选择就要有所牺牲

2,很难搞清楚一个类究竟被装饰了多少层,可能是1层,也可能是100层


简单理解设计模式之装饰者模式

闲话不多说,今天来谈谈装饰者模式: 首先,我觉得要学习设计模式,记住它的定义真的挺重要的,或者一开始的时候你不了解,但是后面理解模式的内涵之后,你会发现定义的精辟。 装饰者模式:动态地将责任附加到...
  • YQYnsmile
  • YQYnsmile
  • 2016年09月26日 21:26
  • 1283

设计模式实战应用之三:装饰者模式

装饰者模式的定义        装饰者模式是应用最普遍的设计模式之一。伟大的 Java 缔造者们将设计模式的应用发挥到了极致,作为解释型语言的 Java 从诞生到今天始终能够作为最主流与应用最广泛的语...
  • defonds
  • defonds
  • 2014年01月03日 21:17
  • 6935

设计模式 装饰者模式 带你重回传奇世界

今天继续设计模式之旅,给大家带来装饰者模式,国际惯例,先看定义。 装饰者模式:若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上。 先简单描述下装饰者模式发挥作用的地方,当我...
  • lmj623565791
  • lmj623565791
  • 2014年04月21日 20:21
  • 17664

装饰者模式 java代码小示例

1、定义及作用该模式以对客户端透明的方式扩展对象的功能。2、涉及角色抽象构件角色:定义一个抽象接口,来规范准备附加功能的类。具体构件角色:将要被附加功能的类,实现抽象构件角色接口。抽象装饰者角色:持有...
  • xiaoquanhuang
  • xiaoquanhuang
  • 2011年04月08日 20:07
  • 2843

学习、探究Java设计模式——装饰者模式

定义装饰者模式:在不改变原类文件以及不使用继承的情况下,动态地将责任附加到对象上,从而实现动态拓展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。设计原则要使用装饰者模式,需要满...
  • a553181867
  • a553181867
  • 2016年08月03日 22:52
  • 4434

我所理解的设计模式(C++实现)——装饰者模式(Decorator Pattern)

解决的问题: 我们在装饰新家的时候买了几幅抽象画,买回来之后发现有些加上色彩艳丽的边框更适合我们,而有的加上玻璃罩之后更能符合我们的使用。那我们来怎么解决这个问题呢?他需要动态的给别的对象增加额...
  • tanningzhong
  • tanningzhong
  • 2015年01月24日 14:47
  • 571

最常用的设计模式---装饰者模式(C++实现)

最常用的设计模式---适配器模式(C++实现)
  • lh844386434
  • lh844386434
  • 2014年01月06日 22:39
  • 2017

设计模式总结之Decorator Pattern(装饰者模式)

装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。...
  • cooldragon
  • cooldragon
  • 2016年08月11日 00:49
  • 1660

装饰者模式(Decorator Pattern)(一):装饰者模式介绍

一、意图 装饰者模式(又称装饰模式、包装(Wrapper)模式):动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。 二、适用性 以下...
  • jialinqiang
  • jialinqiang
  • 2013年05月11日 08:45
  • 1757

装饰者模式及其应用

装饰者模式及其应用前几天看了鸿洋大神的 Android 优雅的为RecyclerView添加HeaderView和FooterView,发现装饰者模式 在某些情况下是设计得如此 优雅,现在总结如下: ...
  • gdutxiaoxu
  • gdutxiaoxu
  • 2016年07月11日 23:52
  • 8827
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:装饰者模式
举报原因:
原因补充:

(最多只允许输入30个字)