本文是阅读《Head First 设计模式》的学习记录。详细内容可以自行阅读书本
装饰者模式
定义
动态的将责任附加到对象上。想要扩展功能,装饰者提供有别于继承的另一种选择。
注意:装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变复杂。
设计原则
对扩展开放,对修改关闭。
举例
有一家咖啡店需要开发订单系统,系统需要打印咖啡内容并算出咖啡的价格。首先咖啡的品种繁多,其中可加入的配料也很多。
问题分析
如果将每种情况的咖啡单独通过继承基类实现(加豆奶的拿铁、加摩卡的深焙咖啡、加豆奶和摩卡的深焙咖啡…),这样会造成子类超多,且不能够随意拓展修改。
这时我们需要使用装饰者模式,将咖啡品种当作组件单独使用。把每种配料当成装饰者,来对组件进行包装使用。
注意:
1.装饰者模式需要和组件(也就是被装饰者)有相同的超类型。
2.我们可以用一个或者多个装饰者来包装一个组件对象。
3.装饰者可以在所委托组件的行为之前与/或之后,加上组件的行为,达到特定行为。
代码
1.创建组件和装饰者的抽象类。(装饰者也继承自组件,也就是被装饰者)
public abstract class Beverage {
String description = "unknown Beverage";
//获取咖啡的描述
public String getDescription() {
return description;
}
//计算价格
public abstract int cost();
}
public abstract class CondimentDecorator extends Beverage{
public abstract String getDescription();
}
2.组件的具体实现(也就是咖啡品种的实现)
public class DarkRoast extends Beverage{
public DarkRoast() {
description = "DarkRoast";
}
@Override
public int cost() {
return 10;
}
}
------------------------------------------------------------------
public class Espresso extends Beverage{
public Espresso() {
description = "Espresso";
}
@Override
public int cost() {
return 10;
}
}
3.装饰者的具体实现(也就是咖啡配料实现)
public class Mocha extends CondimentDecorator{
Beverage beverage;
//构造方法中记录组件变量
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
//调用被装饰者的描述方法
return beverage.getDescription() + " + Mocha";
}
@Override
public int cost() {
//调用被装饰者的计算方法
return beverage.cost() + 1;
}
}
---------------------------------------------------------------------------------------------
public class Milk extends CondimentDecorator{
Beverage beverage;
public Milk(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + " + Milk";
}
@Override
public int cost() {
return beverage.cost() + 1;
}
}
4.测试
public static void main(String[] args) {
Beverage beverage = new Espresso();
beverage = new Milk(beverage);
beverage = new Milk(beverage);
beverage = new Mocha(beverage);
System.out.println("Description = " + beverage.getDescription());
System.out.println("cost = " + beverage.cost());
}