装饰器模式
1. 概念
装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
比如,对于单纯的一幅画,其一般放入画框,然后将画框挂在墙上。在挂在墙上之前,画被蒙上玻璃,装到框子里,这时画、玻璃和画框形成了一个物体。
一般地,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。对比而言,就增加功能来说,装饰器模式相比生成子类更为灵活。
- 优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
- 缺点:多层装饰比较复杂。
插叙

Component
——抽象组件角色,定义一组抽象的接口,规定这个被装饰组件都有哪些功能ConcreteComponent
——实现这个抽象组件的所有功能Decorator
——装饰器角色,它持有一个Component
对象实例的引用,定义一个与抽象组件一致的接口ConcreteDecorator
——具体的装饰器实现者,负责实现装饰器角色定义的功能
Java I/O中的装饰器模式:

- 抽象组件:
InputStream
- 具体组件:
FileInputStream
- 装饰角色:
FilterInputStream
- 具体的装饰器实现者:
BufferedInputStream
装饰器与适配器模式都有一个别名就是包装模式(Wrapper),它们看似都是起到包装一个类或对象的作用,但是使用它们的目的很不一样。
- 适配器模式的意义是要将一个接口转变成另外一个接口,它的目的是通过改变接口来达到重复使用的目的;
- 而装饰器模式不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能,或者改变原有对象的处理方法而提升性能。
2. 示例
下面,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。
我们创建一个 Shape
接口和实现了 Shape
接口的实体类,然后创建一个实现了 Shape
接口的抽象装饰类 ShapeDecorator
,并把 Shape
对象作为它的实例变量。
令 RedShapeDecorator
是实现了 ShapeDecorator
的实体类, DecoratorPatternDemo
类使用 RedShapeDecorator
来装饰 Shape
对象。
创建一个接口
public interface Shape { void draw(); }
创建实现接口的实体类
public class Rectangle implements Shape { @Override public void draw() { System.out.println("Shape: Rectangle"); } }
public class Circle implements Shape { @Override public void draw() { System.out.println("Shape: Circle"); } }
创建实现了
Shape
接口的抽象装饰类public abstract class ShapeDecorator implements Shape { protected Shape decoratedShape; public ShapeDecorator(Shape decoratedShape){ this.decoratedShape = decoratedShape; } public void draw(){ decoratedShape.draw(); } }
创建扩展了
ShapeDecorator
类的实体装饰类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"); } }
使用
RedShapeDecorator
来装饰 Shape 对象public class DecoratorPatternDemo { public static void main(String[] args) { Shape circle = new Circle(); ShapeDecorator redCircle = new RedShapeDecorator(new Circle()); ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle()); //Shape redCircle = new RedShapeDecorator(new Circle()); //Shape redRectangle = new RedShapeDecorator(new Rectangle()); System.out.println("Circle with normal border"); circle.draw(); System.out.println("\nCircle of red border"); redCircle.draw(); System.out.println("\nRectangle of red border"); redRectangle.draw(); } }
执行程序,输出结果: Circle with normal border Shape: Circle Circle of red border Shape: Circle Border Color: Red Rectangle of red border Shape: Rectangle Border Color: Red