定义
动态给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更为灵活。
类型
结构性模式
适用性
以下情况适用Decorator
模式:
- 在不影响其他类的情况下,以动态、透明的方式给单个对象增加职责;
- 处理那些可以撤销的对象;
- 当不能采用生成子类的方法时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被影藏,或类定义不能用于生成子类。
结构
参与者
- Component: 定义一个对象接口,可以给这些对象动态的添加职责;
- ConcreteComponent: 定义一个对象,可以给这个对象添加一些职责;
- Decorator: 维持一个指向
Component
对象的指针,并定义一个与Component
接口一致的接口。Java
中通常为抽象类。 - ConcreteDecorator: 向组件添加职责;
优缺点
- 优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
- 缺点:多层装饰比较复杂。
代码样例
1. 组件对象接口Component
public interface Drink {
float cost();
String getDescription();
}
2.具体组件ConcreteComponent
public class Coffee implements Drink {
@Override
public float cost() {
return 10;
}
@Override
public String getDescription() {
return "Coffe";
}
}
3.抽象装饰器Decorator
public abstract class AbstractDecorator implements Drink {
Drink decorator;
AbstractDecorator(Drink decorator) {
this.decorator = decorator;
}
@Override
public float cost() {
return decorator.cost();
}
@Override
public String getDescription() {
return decorator.getDescription();
}
}
4.具体装饰器ConcreteDecorator
public class MilkDecorator extends AbstractDecorator {
public MilkDecorator(Drink decorator) {
super(decorator);
}
@Override
public float cost() {
return super.cost() + 2;
}
@Override
public String getDescription() {
return super.getDescription() + ", Milk";
}
}
public class SugarDecorator extends AbstractDecorator {
public SugarDecorator(Drink decorator) {
super(decorator);
}
@Override
public float cost() {
return super.cost() + 1;
}
@Override
public String getDescription() {
return super.getDescription() + ", Sugar";
}
}
4.客户端Client
public class Client {
public static void main(String... args) {
new Client().test();
}
private void test() {
Drink drink = new Coffee();
System.out.println(drink.getDescription() + ":" + drink.cost());
drink = new MilkDecorator(drink);
System.out.println(drink.getDescription() + ":" + drink.cost());
drink = new SugarDecorator(drink);
System.out.println(drink.getDescription() + ":" + drink.cost());
drink = new SugarDecorator(drink);
System.out.println(drink.getDescription() + ":" + drink.cost());
}
}
参考代码
https://github.com/xueyufish/design-pattern-java/tree/master/decorator