装饰器设计模式

76 阅读3分钟

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

  1. 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.
  2. The disadvantage of decorator design pattern is that it uses a lot of similar kind of objects (decorators).
  3. Decorator pattern is used a lot in Java IO classes, such as FileReader, BufferedReader etc.

装饰器模式在JDK源码中的应用

装饰器模式在源码中应用得非常多,在JDK中体现最明显的类就是与I/O相关的类,如BufferedReader、InputStream、OutputStream,看一下常用的InputStream的类图,如下图所示。 在这里插入图片描述