设计模式:装饰模式(Head First版)
装饰者模式:动态地将责任附加到对象上,若到扩展功能,装饰者提供了比继承更有弹性的替代方案。
?
UML图
?
有这样一个需求,咖啡店出售各式咖啡,如深焙、低卡、摩卡等,也有各种调料,如牛奶、奶泡等。
咖啡店需要根据咖啡中所放入的不同调料收取不同的费用。用装饰者模式来实现
?
定义一个抽象组件
?
package com.headfirst.chapter3;/** * 定义了一个抽象类,用于表示组件,它定义了一个抽象方法cost */public abstract class Beverage {String description; public String getDescription() {return description;}public abstract double cost();//计费方法}
?
?
下面两个是具体组件,也就是被装饰者
1,深焙咖啡
?
package com.headfirst.chapter3;public class DarkRoast extends Beverage {//深焙咖啡public DarkRoast() {this.description = "DarkRoast";}public double cost() {return 0.89;}}
?
2,混合咖啡
?
package com.headfirst.chapter3;public class HouseBlend extends Beverage {public HouseBlend() {this.description = "HouseBlend";}public double cost() {return 1.89;}}
?
?
装饰者
这里定义了一个抽象方法getDescription,那么子类必须它来增加描述
如Houseblend Milk
package com.headfirst.chapter3;public abstract class CondimentDecorator extends Beverage {public abstract String getDescription();}?
?
?
?下面两个是装饰者
?
package com.headfirst.chapter3;public class Milk extends CondimentDecorator {private Beverage beverage;//这个引用指向被装饰者public Milk(Beverage beverage) {this.beverage = beverage;}public String getDescription() {return beverage.getDescription() + " Milk";}public double cost() {return beverage.cost() + 0.20;}}
?
?
?
package com.headfirst.chapter3;public class Mocha extends Beverage {Beverage beverage;public Mocha(Beverage beverage) {this.beverage = beverage;}public String getDescription() {return beverage.getDescription() + " Mocha";}public double cost() {return beverage.cost()+0.59;}}?
?
测试类:
?
package com.headfirst.chapter3;public class Test {public static void main(String[] args) {Beverage darkRoast = new DarkRoast();darkRoast = new Mocha(darkRoast);darkRoast = new Milk(darkRoast);System.out.println(darkRoast.getDescription()+" $"+darkRoast.cost());}}
?最后打印出:DarkRoast Mocha Milk $1.68
?
设计原则:类应该向修改关闭,向扩展开放类的继承是扩展开幕式之一,但不见得是达到弹性设计的最佳方式。如果依赖继承,那么类的行为只能在编译时静态决定。反之,利用组合,可以把装饰者混合着用,而且是在运行时。