装饰模式

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活是对继承的有力补充

扩展一个类的功能会使用继承方式来实现。但继承具有静态特征耦合度高,并且随着扩展功能的增多,子类会很膨胀。装饰器模式的目标是使用组合关系来创建一个装饰对象来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能。

装饰器模式结构图

实现

抽象构件角色:定义一个抽象接口以规范准备接收附加责任的对象。

1
2
3
public interface Component {
void operation();
}

具体构件角色:实现抽象构件,通过装饰角色为其添加一些职责。

1
2
3
4
5
6
public class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("ConcreteComponent operation");
}
}

抽象装饰角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。

1
2
3
4
5
6
7
8
9
10
11
12
public abstract class Decorator implements Component {
private Component component;

public Decorator(Component component) {
this.component = component;
}

@Override
public void operation() {
this.component.operation();
}
}

具体装饰角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

1
2
3
4
5
6
7
8
9
10
11
12
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
public void operation() {
super.operation();
addedFunction();
}
public void addedFunction() {
System.out.println("为具体构件角色增加额外的功能addedFunction()");
}
}

场景类

1
2
3
4
5
6
public static void main(String[] args) {
Component p = new ConcreteComponent();
p.operation();
Component d = new ConcreteDecorator(p);
d.operation();
}

只有一个具体构件没有抽象构件时,可以让抽象装饰继承具体构件。若只有一个具体装饰时,可以将抽象装饰和具体装饰合并。

优点

  • 装饰类和被装饰类可以独立发展, 而不会相互耦合;
  • 装饰模式是继承关系的一个替代方案;
  • 装饰模式可以动态地扩展一个实现类的功能;

缺点

装饰器模式会增加许多子类,过度使用会增加程序得复杂性,尽量减少装饰类的数量, 以便降低系统的复杂度。

应用场景

  • 需要扩展一个类的功能, 或给一个类增加附加功能,而又不能采用生成子类的方法进行扩充时;

  • 需要动态地给一个对象增加功能, 这些功能可以再动态地撤销

  • 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现;

    Java I/O 标准库的设计,InputStream的子类FilterInputStreamOutputStream的子类FilterOutputStreamReader的子类BufferedReader以及FilterReader,还有Writer的子类BufferedWriterFilterWriter以及 PrintWriter等,它们都是抽象装饰类。

1
2
BufferedReader in = new BufferedReader(new FileReader("filename.txt"));
String s = in.readLine();