装饰器模式(Decorator Pattern):动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案
类图:
用户需求:Starbuzz是以扩张速度最快而闻名的咖啡连锁店,Beverage(饮料)是一个抽象类,cost() 方法是抽象的,下面各种咖啡,购买时加入各种调料
需求分析:每种咖啡都是具体的子类,这里如果一旦有个调料如milk价格变更,那就需要修改所有相关的子类代码,这样下去,项目组就要黄了,这里就涉及一个涉及设计原则:类应该对扩展开放,对修改关闭。
类图设计:
代码示例:
组件Beverage(饮料):
package Decorator;
public abstract class Beverage {
String description = "UnKnown Beverage";
public String getDescription() {
return description;
}
// 必须在子类中实现
public abstract double cost();
}
装饰类CondimentDecorator
package Decorator;
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
实现Beverage的具体对象
package Decorator;
public class Espresso extends Beverage {
public Espresso() {
// 变量继承自Beverage
description = "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
实现Beverage的具体对象
package Decorator;
public class HouseBlend extends Beverage {
public HouseBlend() {
// 变量继承自Beverage
description = "HouseBlend";
}
@Override
public double cost() {
return 0.89;
}
}
实现装饰类的调料Milk
package 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.21 + beverage.cost();
}
}
实现装饰类的调料Mocha
package 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.20 + beverage.cost();
}
}
测试类代码
package Decorator;
public class StarbuzzCoffee {
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
Beverage beverage2 = new Mocha(beverage);
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
Beverage beverage3 = new Milk(beverage2);
System.out.println(beverage3.getDescription() + " $" + beverage3.cost());
}
}
Espresso $1.99
Espresso, Mocha $2.19
Espresso, Mocha, Milk $2.4
装饰链:Espresso(1.99)——被Mocha装饰(加上0.2)——被Milk装饰(加上0.21)——最后为 $2.4 。
更多的例子详解——传送门
装饰器在Java JDK中应用很多,最典型的就是IO,类图
装饰链:FileInputStream——被装饰后BufferedInputStream——被装饰后LineNumberInputStream