定义
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装
装饰器模式是对象结构动态修改方式,相较于继承关系,装饰器更加灵活,和代理模式相比,装饰器模式更偏重与对象本质行为或者属性的加强,比如窗口系统添加主题。而代理模式则更偏重于非本质行为的添加,比如文件系统中添加权限管理和修改日志。
实例
public interface Shape {
void draw();
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Circle");
}
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape){
System.out.println("Border Color: Red");
}
}
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}
public void draw(){
decoratedShape.draw();
}
}
其类图关系为:
上述是给Shape实例添加边框的实例,从功能角度出发,使用继承并重写draw方法就可以实现边框,只是有多少个需要边框的shape子类,就需要重写多少个类,这样类的数量很容易会爆炸,而采用包装器模式,保持该包装器职责单一,这里RedShapeDecorator类只负责添加红色边框(实际上不应该硬编码为红色),如果Circle类需要边框,也可以直接用RedShapeDecorator包装一下就行,而且多个包装器可以相互组合包装,能组合出复杂的功能。
总结
优点:
- 装饰类和被装饰类是可以独立的,低耦合的。互相都不用知道对方的存在
- 装饰模式是继承的一种替代方案,无论包装多少层,返回的对象都是is-a的关系(上面的例子:包装完还是Phone类型)。
- 实现动态扩展,只要继承了装饰器就可以动态扩展想要的功能了。
缺点:
- 多层装饰是比较复杂的,提高了系统的复杂度。不利于我们调试
在Java中,对类功能增强的方式三种:
- 继承:重写或者修改类原有行为和属性
- 代理模式:主要用于增加类非本质功能和属性,其本质上不是增强类原有功能,而是增加类非本质功能
- 包装器模式: 主要用于增强类本质功能和属性,其本质是增强类原有能力