装饰器模式
装饰器模式可以动态地给一个对象添加额外的职责、功能,进行功能的扩展,不必改变原始的继承关系,通过创建包装对象来实现,其本质就是动态组合,比生成子类更为灵活
附加职责
核心概念
- Component 组件对象接口,给这些对象动态地添加职责
- ConcreteComponent 具体的组件对象
- Decorator 所有装饰器的父类,需要定义一个与组件接口一致的接口,并持有一个Component对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| public abstract class Component {
public abstract void operation(); }
public class ConcreteComponent extends Component{ @Override public void operation() { System.out.println("-----"); } }
public abstract class Decorator extends Component {
private Component component;
public Decorator(Component component){ this.component = component; }
@Override public void operation() { component.operation(); } }
public class ConcreteDecoratorA extends Decorator{
public ConcreteDecoratorA(Component component) { super(component); }
@Override public void operation() { super.operation(); addBehavior(); }
private void addBehavior(){ System.out.println("A"); } }
public class ConcreteDecoratorB extends Decorator{
public ConcreteDecoratorB(Component component) { super(component); }
@Override public void operation() { super.operation(); addBehavior(); }
private void addBehavior(){ System.out.println("B"); } }
|
如java io包中的设计就是使用了修饰者模式
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class BufferedInputStream extends FilterInputStream {
protected volatile InputStream in;
public BufferedInputStream(InputStream in) { this(in, DEFAULT_BUFFER_SIZE); }
}
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
|
优缺点
优点
- 比使用继承更灵活,通过一种动态的方式来扩展一个对象的功能,在运行时可以选择不同的装饰器来实现不同的行为
- 通过使用不同的具体装饰类以及这些修饰类的排列组合,可以创造出很多不同行为的组合,可以使用多个具体装饰类来装饰同一个对象,得到功能更强大的对象
- 具体构件类与具体装饰类可以独立变化,是低耦合的
- 更容易复用功能,把一系列复杂的功能分散到每个装饰器中,一般一个装饰器只实现一个功能,这样有利于装饰器功能的复用
- 简化高层定义,可以通过组合装饰器的方式,为对象增加任意多的功能
缺点
- 会产生很多的小对象,增加了系统的复杂性
- 层次过多,排错需要逐级调试排查
使用场景
- 需要扩展一个类的功能,或给一个类添加附加职责
- 需要动态的给一个对象增加功能
- 当不能采用生成子类的方式进行扩充时(如类定义为final的)
- 在不影响其他对象的情况下,以动态、透明的方式给对象添加职责