设计模式学习(三)之装饰者模式

来源:互联网 发布:太空工程师 编程教程 编辑:程序博客网 时间:2024/05/20 18:55
设计原则:类应该对扩展开放,对修改关闭
我们的目标是允许类容易扩展,在不修改代码的情况下,就可以搭配新的行为,如能实现这样的目标,这样的设计具有弹性,可以应对改变,可以接受新的功能来应对改变的需求
装饰者和被装饰者对象有相同的超类型
可以用一个或者多个装饰者包装一个对象
既然装饰者和被装饰者有相同的超类型,所以在任何需要原始对象的场合,可以用装饰过的对象代替它
装饰者模式:动态的将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案
装饰者类图

看个具体问题:
有一个咖啡店,他们有几种饮料,比如HouseBlend, DarkRoast.Decaf,Espresso
每种饮料里面可以加调料,可以加一种或者几种,也可以不加,调料有,SteamedMilk.Soy,Mocha等
计算一杯饮料的价格,包括饮料的价格和调料的价格
看一下类图

那么问题来了
如果需要添加新的调料,需要加上新的方法
如果价格修改了,需要修改父类的代码
有些饮料并不适合某些调料,仍然加入了判断
如果需要加入双倍的某种调料呢?

看新的类图

用代码来实现 
package com.alvin.decorator;public abstract class Beverage {protected String description;public abstract String getDescription();public abstract float cost();}
package com.alvin.decorator;public class HouseBlend extends Beverage{public float cost(){return 1;}@Overridepublic String getDescription() {return "HouseBlend";}}
package com.alvin.decorator;public class Decaf extends Beverage {@Overridepublic String getDescription() {return "Decaf";}@Overridepublic float cost() {return 3;}}
package com.alvin.decorator;public class DarkRoast extends Beverage {@Overridepublic String getDescription() {return "DarkRoast";}@Overridepublic float cost() {return 2;}}
package com.alvin.decorator.impl;import com.alvin.decorator.Beverage;public abstract class CondimentDecorator extends Beverage {}
package com.alvin.decorator.impl;import com.alvin.decorator.Beverage;public class Milk extends CondimentDecorator {private Beverage beverage;public Milk(Beverage beverage) {this.beverage = beverage;}@Overridepublic String getDescription() {return  beverage.getDescription() + "Milk";}@Overridepublic float cost() {return beverage.cost() + 0.2f;}}
package com.alvin.decorator.impl;import com.alvin.decorator.Beverage;public class Mocha extends CondimentDecorator {private Beverage beverage;public Mocha(Beverage beverage) {this.beverage = beverage;}@Overridepublic String getDescription() {return beverage.getDescription() + "Mocha";}@Overridepublic float cost() {return beverage.cost() + 0.1f;}}
package com.alvin.decorator.impl;import com.alvin.decorator.Beverage;public class Soy extends CondimentDecorator {private Beverage beverage;public Soy(Beverage beverage) {this.beverage = beverage;}@Overridepublic String getDescription() {return beverage.getDescription() + "Soy";}@Overridepublic float cost() {return beverage.cost() + 0.3F;}}
package com.alvin.decorator;import com.alvin.decorator.impl.Milk;import com.alvin.decorator.impl.Mocha;import com.alvin.decorator.impl.Soy;public class Run {public static void main(String[] args) {Beverage beverage = new DarkRoast();System.out.println(beverage.getDescription() + beverage.cost());Beverage beverage1 = new HouseBlend();beverage1 = new Mocha(beverage1);beverage1 = new Milk(beverage1);beverage1 = new Soy(beverage1);System.out.println(beverage1.getDescription() + beverage1.cost());}}
运行结果
DarkRoast2.0
HouseBlendMochaMilkSoy1.6000001
在看一个JDK里面的类图来帮助理解输入输出流