一、什么情况下考虑使用“装饰者模式”?
当我们需要将责任动态的附加到对象上的时候;也就是说,我们开发设计的对象中有某一部分的功能现在还不能确定,以后需要动态的添加或者去掉。或者是在使用继承比较困难的时候,可以采用组合的实现方式(继承与复用)。
结合下面一个实际可能应用的场景来进行分析:
此为某一咖啡店的简单的菜单系统,其中所有的咖啡必须继承自Beverage类,咖啡中需要根据顾客的要求,加入巧克力、豆浆等调料,然后依据加入的调料的不同收取相应的费用。
eg:菜单上的StarbuzzCoffee实际为:HouseBlend + 2 * Mocha + Soy 调制而成,该如何实现呢?
如果采用装饰着模式的话可以让Mocha来装饰StarBuzzCoffee,然后Soy来装饰Mocha,在计算价格时只需要由外到内依次调用相应的价格即可。
装饰者模式的一些概念:
①装饰者和被装饰者有相同的超类型
②你可以用一个或者多个装饰者包装一个对象。
③由于装饰者和被装饰对象具有相同的对象,所有在任何需要原始对象的时候,可以用装饰后的对象来替换它
④装饰者可以在所委托被装饰者的行为之前或者之后,加上自己的行为,以实现特定的功能。
⑤对象可以在任何时候被装饰,你可以在运行时选择你喜欢的装饰者来装饰对象。
二、如何实现装饰者模式?
①查看已有具体组件:如HouseBlend和Espresso,代码如下
public abstract class Beverage { protected String description = "Unknown Beverage"; public String getDescription() { return description; } public abstract double cost(); }
public class HouseBlend extends Beverage { public HouseBlend(){ description="HouseBlend"; } @Override public double cost() { return .89; } }
②定义抽象的装饰者(也可以不用),同时定义具体的装饰者,装饰者的目的就是增加行为到被包装的对象上,关键这在于“装饰”,所以我们采用组合让Beverage作为具体装饰者的field,同时装饰者也必须继承自Beverage,这样才可以对其进行进一步的装饰。
public class Mocha extends CondimentDecorator { protected Beverage beverage;//被包装对象 public Mocha(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription() + ", Mocha"; } @Override public double cost() { return .20 + beverage.cost(); } }
③装饰出需要的咖啡
public class StarbuzzCoffee { public static void main(String[] args) { Beverage beverage = new HouseBlend(); beverage = new Soy(beverage); beverage = new Mocha(beverage); beverage = new Mocha(beverage); System.out.println(beverage.getDescription() + " $" + beverage.cost()); } }
java中典型使用装饰者模式的地方就是Java IO,感兴趣的话可以深入学一下。
ps:在编写上面的代码时发生了一个小插曲:发现最后输入的结果为:
HouseBlend ,Soy, Mocha, Mocha $1.5899999999999999
这一定不是我们想看到的结果,
这是由于float和double视为科学计算和工程计算而设计的,它们执行的为较为精确的快速近似计算,所以不能提供完全精确的结果。
所以为实现精确的计算可以使用BigDecimal
我们将其中的cost()修改如下:
@Override public double cost() { BigDecimal cost = new BigDecimal("0.20"); return (cost.add(new BigDecimal(Double.toString(beverage.cost()))).doubleValue()); }
便可以得出想要的结果了。
如果不使用BigDecimal可以将小数先转换为int或者long类型,最后在除以相应的值即可。
另外注意到了没,BigDecimal新建时使用的构造方法为为String,而没有使用double,这是为什么??
Notes:
- The results of this constructor can be somewhat unpredictable. One might assume that writing
new BigDecimal(0.1)
in Java creates aBigDecimal
which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as adouble
(or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding. - The
String
constructor, on the other hand, is perfectly predictable: writingnew BigDecimal("0.1")
creates aBigDecimal
which is exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the String constructor be used in preference to this one. - When a
double
must be used as a source for aBigDecimal
, note that this constructor provides an exact conversion; it does not give the same result as converting thedouble
to aString
using theDouble.toString(double)
method and then using theBigDecimal(String)
constructor. To get that result, use thestatic
valueOf(double)
method.
相关推荐
装饰器模式是面向对象设计模式的一种,主要用于在不改变原有对象结构的情况下,动态地为对象增加新的功能。这种模式在Java中尤其常见,因为它允许我们遵循“开闭原则”——对扩展开放,对修改关闭。 装饰器模式的...
装饰模式是一种设计模式...通过阅读和理解《设计模式:可复用面向对象软件的基础》等经典书籍,以及像博客“设计模式——装饰模式”这样的在线资源,我们可以深入掌握并灵活运用装饰模式,提高代码的可维护性和扩展性。
《Java与模式——源码》这个主题涉及到的是Java编程语言中的设计模式应用,以及如何通过源代码来理解和学习这些模式。设计模式是软件工程中的一种最佳实践,它们是解决常见问题的经验总结,使得代码更易读、易维护、...
本资料“《java设计模式》课后习题模拟试题解答——刘伟.zip”主要涵盖了Java设计模式的学习与应用,特别是针对刘伟教授的相关课程的课后习题及模拟试题的解答。 设计模式分为三大类:创建型、结构型和行为型模式。...
在编程世界中,Java设计模式是面向对象编程领域的一个重要概念,它为解决常见的软件设计问题提供了可重用的解决方案。对于新手来说,设计模式可能显得深奥难懂,但它们实际上是经验丰富的开发者用来提高代码质量、可...
《设计模式——Java语言中的应用》是一本专为Java开发者深入理解面向对象设计而编写的经典书籍。设计模式是软件工程领域中经过实践验证的、解决常见问题的有效方案,它们代表了在特定上下文中,针对特定问题的最优...
本章可以称为“给爱用继承的人一个全新的设计眼界”。我们即将再度探讨典型滥用问题。你将在本章学到如何使用对象组合的方式,做到在运行时装饰类。为什么呢?一旦你熟悉了装饰者的技巧...——《Head First 设计模式》
《Java设计模式》是刘伟老师的一本经典教材,它深入浅出地讲解了软件设计中的重要概念——设计模式。设计模式是经验丰富的开发者在解决常见问题时总结出的通用解决方案,是软件开发中的智慧结晶。这本书的课后习题和...
装饰模式是一种设计模式,属于结构型模式,其主要目的是在不改变对象本身的基础上,通过向对象添加新的行为或属性来扩展其功能。这种模式遵循“开闭原则”,即对扩展开放,对修改关闭。 在装饰模式中,有四个关键...
在博客文章“装饰者模式——Decorator”中,作者可能详细讲解了以下几个方面: 1. 装饰者模式的基本概念和原理。 2. 如何通过代码示例展示装饰者模式的实现。 3. 装饰者模式与继承的区别和优势。 4. 装饰者模式在...
### JAVA设计模式总结之23种设计模式及六大原则 #### 一、设计模式之六大原则 ##### 总原则:开闭原则(Open Close Principle) 开闭原则是设计模式中最核心的原则之一,它强调的是软件实体(类、模块、函数等)...
### Java设计模式经典教程知识点概览 #### 一、设计模式概述 设计模式是一种软件设计方法,它为软件开发者提供了一种标准化的方式去解决常见的软件设计问题。设计模式的使用可以提高代码的可读性和可维护性,同时...
Java设计模式是软件开发中的重要概念,它是一种在特定情境下解决问题的经验总结,可以提高代码的可读性、可维护性和可复用性。在这个压缩包文件“DesignPatterns”中,很可能包含了各种Java设计模式的源代码实现。...
目录: 前 言 第一部分 大旗不挥,谁敢冲锋——热身篇 第1章 单一职责原则 1.1 我是“牛”类,我可以担任多职吗 1.2 绝杀技,打破你的传统思维 1.3 我单纯,所以我快乐 1.4 最佳实践 ...附录:23个设计模式
"大牛解读Java设计模式.pdf"这本书籍,作为这个主题的载体,很可能是由资深专家撰写,用生动的语言和实例帮助读者理解抽象的设计概念,从而提升他们的编程技能。无论你是初学者还是有经验的开发者,都能从中受益匪浅...
在这个实验报告中,主要讨论了三种设计模式——策略模式、装饰模式和工厂模式的综合运用,以解决一个国际电子商务系统的订单处理问题。 1. **策略模式**: 策略模式的核心在于将算法族封装在独立的可互换的策略类...
"深入浅出设计模式三——Beverage实现(装饰者模式)"这一标题指出,我们将探讨如何使用装饰者模式来实现一个饮品系统。装饰者模式是一种结构型设计模式,它允许我们在运行时向对象添加新的行为或职责,而无需修改对象...
根据提供的标题、描述以及部分内容,本文将深入探讨Java设计模式,并着重分析23种常见的设计模式,以帮助Java程序员更好地理解和应用这些模式。 ### Java设计模式概述 Java设计模式是面向对象软件设计的一种通用可...