设计模式-装饰器
作者:互联网
装饰器
概念
动态的将职责附加到对象上。对于某类对象的功能扩展来讲,装饰模式比继承更有弹性。
运行时期的扩展远比编译期的继承威力大。
UML类图
UML类图说明
1)每个组件都可以单独使用,或者被装饰者包裹起来使用
2)每个装饰者(ConcreteDecoratorA, ConcreteDecoratorB)都有一个实例变量用以保存某个Component的引用
3)Decorator可以是装饰者共同实现的接口或抽象类
4)ConcreteComponent扩展自Component,是我们将要动态添加新行为的对象
5)装饰者可以扩展Component的状态
6)Component记录所装饰的事物即装饰者包裹着的Component
7)装饰者可以添加新的方法,新行为是通过在旧行为前面或后面做一些计算来添加的
案例
星巴兹是一家连锁咖啡店,它们的订单系统如下
实现说明
1)Beverage是一个抽象类,店内的所有饮料都必须继承此类
2)description这个实例变量由子类来设置,利用getDescription返回此变量内容
3)每个子类实现cost()来返回饮料的价格
需求变更:购买咖啡时,也可以添加各种调料,如蒸奶、豆浆等,星巴兹会根据加入的调料收取不同的费用
实现1:
增加类来满足需求的变更,比如,HouseBlendWithStemedMilk, HouseBlendWithStemedMilkandMocha等待
分析:
这简直是个类爆炸,制造了一个维护噩梦,每新增一种调料,就要新增一个或多个类来满足需求,
如果牛奶的价格上涨怎么办?
并且者也违反了两个原则:多用组合,少用继承;封装变化
实现2:
利用实例变量和继承来追踪这些调料
实现说明
1)超类cost()用于计算所有调料的价格,子类覆盖超类的cost()方法,把指定的饮料类型的价格加进来
2)子类中的每个cost()方法需要计算饮料的价格,然后通过调用父类的cost()实现加入调料的价格
分析:
这种方法有潜在的问题
调料价格的改变会使我们改变现有的代码
V
一旦新的调料出现,我们不仅要在超类中添加新的方法,
还要在子类中覆盖超类中的cost()方法
V
如果以后再开发出新的饮料(比如,冰茶),某些调料可能并不适合,
但是冰茶仍将继承那些不适合的方法,比如hasWhip()等
V
万一顾客需要双倍mocha怎么办?
使用装饰者模式实现
装饰者小结
1)装饰者和被装饰者对象有相同的超类,即你可以在任何需要的被装饰对象的时候,用装饰者代替它
2)可以用一个或多个装饰者去包装一个对象
3)装饰者可以在被装饰者行为的之前或之后,加上自己的行为已达到特定的目的
4)对象可以在任何时候被装饰,即你可以在运行时动态的、不限量的用你喜欢的装饰者来装饰对象
Java代码实现装饰者模式
Beverage.java
package design.pattern.decorator; public abstract class Beverage { String description = "Unknown beverage"; public String getDescription(){ return description; } public abstract double cost(); }View Code
CondimentDecorator.java
package design.pattern.decorator; public abstract class CondimentDecorator extends Beverage{ public abstract String getDescription(); }View Code
HouseBlend.java
package design.pattern.decorator; public class HouseBlend extends Beverage { public HouseBlend() { description = "HouseBlend"; } @Override public double cost() { return 0.89; } }View Code
DarkRoast.java
package design.pattern.decorator; public class DarkRoast extends Beverage { public DarkRoast() { description = "DarkRoast"; } @Override public double cost() { return 0.99; } }View Code
Decaf.java
package design.pattern.decorator; public class Decaf extends Beverage { public Decaf() { description = "Decaf"; } @Override public double cost() { return 1.05; } }View Code
Milk.java
package design.pattern.decorator; public class Milk extends CondimentDecorator { Beverage beverage; public Milk(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription() + ", Milk"; } @Override public double cost() { return 0.1 + beverage.cost(); } }View Code
Mocha.java
package design.pattern.decorator; public class Mocha extends CondimentDecorator { Beverage beverage; public Mocha(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription() + ", Mocha"; } @Override public double cost() { return 0.2 + beverage.cost(); } }View Code
Soy.java
package design.pattern.decorator; public class Soy extends CondimentDecorator { Beverage beverage; public Soy(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription() + ", Soy"; } @Override public double cost() { return 0.15 + beverage.cost(); } }View Code
Whip.java
package design.pattern.decorator; public class Whip extends CondimentDecorator { Beverage beverage; public Whip(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription() + ", Whip"; } @Override public double cost() { return 0.10 + beverage.cost(); } }View Code
参考资料:《HeadFirst 设计模式》
标签:cost,Beverage,public,beverage,return,设计模式,装饰 来源: https://www.cnblogs.com/marton/p/11494733.html