定义
动态地为一个对象添加一些额外职责,就增加功能而言,装饰者模式相比生成子类更为灵活
从形式上来说它会有点像AOP中的代理模式,通过聚合目标对象来实现功能增强。但不同的是,装饰者模式更灵活,它能够同时嵌套多层也就是为同一个对象增强多次,同时这种增强是根据使用者需求的变化而即时改变的。
双方侧重点不同,装饰者模式的重点在于拓展目标对象的功能,而代理模式则是提供访问控制。
装饰者模式在Java的IO结构中体现的淋漓尽致
结构和实现
结构
从结构上看其实与代理模式就有些相像,通过将继承自同一接口的对象聚合到自身来完成增强,经过装饰后的对象就像洋葱一样,被层层包裹层层增强。
装饰者模式中的角色
- 抽象构件Component
Component是一个接口或者是一个抽象类,定义蓝来我们最核心的对象 - 具体构件ConreateComponent
ConreateComponent核心组件 - 抽象装饰者Decorator
一般是一个抽象类,其中必然包含一个指向Component的私有变量 - 具体装饰者ConcreateDecorator
具体装饰者,能够把最核心的具体构件装饰成其他类,其实就是对具体组件进行多层的代理
实现
我们以奶茶为例,我们都知道奶茶除了最基本的奶茶以外还可以加椰果、珍珠等配料。通过不同的配料,我们可以得到不同的奶茶
抽象构件MilkTea
public interface MilkTea {
}
具体构件BasicMilkTea
public class BasicMilkTea implements MilkTea {
public BasicMilkTea(){
System.out.println("制作了一杯基础奶茶");
}
}
装饰者MilkTeaDecorator
public abstract class MilkTeaDecorator implements MilkTea{
private MilkTea milkTea;
public MilkTeaDecorator(MilkTea _milkTea){
this.milkTea = _milkTea;
}
}
具体装饰者1布丁
public class Pudding extends MilkTeaDecorator{
public Pudding(MilkTea _milkTea) {
super(_milkTea);
System.out.println("增加了一份布丁");
}
}
具体装饰者2砂糖
public class Sugar extends MilkTeaDecorator {
public Sugar(MilkTea _milkTea) {
super(_milkTea);
System.out.println("增加了一份糖");
}
}
测试
现在我们可以点奶茶了,我比较喜欢甜的所以我要加两份糖,同时再加一份布丁
public class DecoratorTest {
public static void main(String[] args) {
MilkTea milkTea = new Sugar(new Sugar(new Pudding(new BasicMilkTea())));
}
}
输出
制作了一杯基础奶茶
增加了一份布丁
增加了一份糖
增加了一份糖
特点
优点
- 装饰者与被装饰者可以独立发展,不会发生耦合
- 该模式是继承的替代方案,上面例子中如果使用继承方案,那么任意一种奶茶都需要为其建立一个新的类。很明显,我们不会这么干。在上面方案中,该模式不关装饰了多少层,返回的对象依旧为顶层接口,实现还是is-a的关系。
- 可动态扩展。实现类的功能
缺点
- 由于包裹了多层,结构过于复杂,出现异常时不太容器排查问题