GoF原文
Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.
装饰器设计模式用于在运行时修改对象的功能,单个对象将获得修改后的行为,同一类的其他实例将不受此影响。
装饰器模式提供了比继承更有弹性的替代方案(扩展原有对象的功能)将功能附加到对象上。因此,装饰器模式的核心是功能扩展。使用装饰器模式可以透明且动态地扩展类的功能。
装饰器模式的应用场景来看这样一个场景
煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么“加码”,都还是一个煎饼。 再比如,给蛋糕加上一些水果,给房子装修,都是装饰器模式。 装饰器模式在代码程序中适用于以下应用场景。 (1)用于扩展一个类的功能,或者给一个类添加附加职责。 (2)动态地给一个对象添加功能,这些功能可以再动态地被撤销。 (3)需要为一批平行的兄弟类进行改装或加装功能。
1. Component Interface – The interface or abstract class defining the methods that will be implemented.
public interface A1_Car {
public void assemble();
}
2. Component Implementation – The basic implementation of the component interface.
public class A2_BasicCar implements A1_Car {
public A2_BasicCar() {
System.out.println("A2_BasicCar 构造方法");
}
@Override
public void assemble() {
System.out.println("Basic Car.");
}
}
3. Decorator – Decorator class implements the component interface and it has a HAS-A relationship with the component interface. Decorator类实现了组件接口,并且它与组件接口具有一个has-a关系。 The component variable should be accessible to the child decorator classes, so we will make this variable protected. 组件变量应该可以被子装饰器类访问,因此我们将这个变量设置为protected。
public class A3_CarDecorator implements A1_Car {
protected A1_Car car;
public A3_CarDecorator(A1_Car c){
this.car=c;
System.out.println("A3_CarDecorator 构造方法");
}
@Override
public void assemble() {
System.out.println("Decorator 被调用前 记录一下.");
this.car.assemble();
System.out.println("Decorator 被调用后 记录一下.");
}
}
4. Concrete Decorators – Extending the base decorator functionality and modifying the component behavior accordingly.
public class A4_SportsCar extends A3_CarDecorator {
public A4_SportsCar(A1_Car c) {
super(c);
System.out.println("A4_SportsCar 构造方法");
}
@Override
public void assemble(){
super.assemble();
System.out.println("装饰1:Adding features of Sports Car.");
}
}
public class A5_LuxuryCar extends A3_CarDecorator {
public A5_LuxuryCar(A1_Car c) {
super(c);
System.out.println("A5_LuxuryCar 构造方法");
}
@Override
public void assemble(){
super.assemble();
System.out.println("装饰3: Adding features of Luxury Car.");
}
}
测试
A1_Car sportsCar = new A4_SportsCar(new A2_BasicCar());
sportsCar.assemble();
System.out.println("*****");
A1_Car luxuryCar = new A5_LuxuryCar(new A2_BasicCar());
luxuryCar.assemble();
System.out.println("*****");
A1_Car sportsLuxuryCar = new A4_SportsCar(new A5_LuxuryCar(new A2_BasicCar()));
sportsLuxuryCar.assemble();
结果
A2_BasicCar 构造方法
A3_CarDecorator 构造方法
A4_SportsCar 构造方法
Decorator 被调用前 记录一下.
Basic Car.
Decorator 被调用后 记录一下.
装饰1:Adding features of Sports Car.
*****
A2_BasicCar 构造方法
A3_CarDecorator 构造方法
A5_LuxuryCar 构造方法
Decorator 被调用前 记录一下.
Basic Car.
Decorator 被调用后 记录一下.
装饰2: Adding features of Luxury Car.
*****
A2_BasicCar 构造方法
A3_CarDecorator 构造方法
A5_LuxuryCar 构造方法
A3_CarDecorator 构造方法
A4_SportsCar 构造方法
Decorator 被调用前 记录一下.
Decorator 被调用前 记录一下.
Basic Car.
Decorator 被调用后 记录一下.
装饰2: Adding features of Luxury Car.
Decorator 被调用后 记录一下.
装饰1:Adding features of Sports Car.
Important Points
- Decorator design pattern is helpful in providing runtime modification abilities and hence more flexible. Its easy to maintain and extend when the number of choices are more.
- The disadvantage of decorator design pattern is that it uses a lot of similar kind of objects (decorators).
- Decorator pattern is used a lot in Java IO classes, such as FileReader, BufferedReader etc.
装饰器模式在JDK源码中的应用
装饰器模式在源码中应用得非常多,在JDK中体现最明显的类就是与I/O相关的类,如BufferedReader、InputStream、OutputStream,看一下常用的InputStream的类图,如下图所示。