装饰器模式
装饰器模式:动态的为一个实例增加额外的功能,装饰器为通过继承来进行功能扩展提供了另一种途径。
当通过继承父类来实现功能的扩展不太现实的时候,装饰器模式是一种很好的方式。
装饰器模式有两个显著的优点:
优点
- 优点1:相比静态的继承父类来达到扩展功能,装饰器模式提供更加灵活的方式来增加额外的功能,装饰器模式能够在运行时动态的增加或者减少功能(一次或者多次);
- 优点2:避免了功能类在继承结构上膨胀;相比与一开始就尝试支持所有可预见的功能,从而设计了一个非常复杂的、自定义的类的方式,装饰器模式则是先定义一个简单的类,然后不断的用装饰器装饰增加功能;由于系统能够自由组合不同的装饰器来达到功能的组合、扩展,因此相比于继承,在子类中就不太会出现冗余的功能;
缺点:由于装饰器模式中的装饰器类仅仅是在某一方面不同,这样在进行复杂的装饰的时候,会产生特别多的小的、比较像的实例对象(装饰器)。
装饰器模式含有几部分:
- Component:定义了能够动态增加功能的对象的接口;
- ConcreteComponent:Component的实现类
- Decorator:持有一个需要被装饰的实例的引用(Component引用),接口遵循Component,满足里氏替换原则;
- ConcreteDecorator:Decorator的实现类;
JDK里面的InputStream、BufferedInputStream 、DataInputStream、FileInputStream等都是利用装饰器模式。
装饰器模式从某种程度和代理模式相仿,但是两者还是有些细微的区别:
- 装饰器模式关注的是动态增加对象实例的功能;而代理模式关注的则是被代理对象访问的控制;
- 装饰器模式是增加类似的功能,是对被装饰类的功能增加;而代理模式则是代理增加非类似的功能;
如果用户更关注的的是装饰器带来的功能,则用装饰器模式;而用户更关注的是原来的被代理类的功能,则使用代理模式。
UML类图
实例
public interface Component {
void operation();
}
public class ConcreteComponent implements Component {
@Override
public void operation() {
// TODO Auto-generated method stub
System.out.println("ConcreteComponent: operation");
}
}
public abstract class Decorator implements Component {
Component component;
public Decorator(Component component) {
this.component = component;
}
}
public class DecoratorA extends Decorator {
public DecoratorA(Component component) {
super(component);
// TODO Auto-generated constructor stub
}
@Override
public void operation() {
// TODO Auto-generated method stub
addtionalOperationA();//decorate operation
this.component.operation();
}
public void addtionalOperationA() {
System.out.println("addtionalOperationA");
}
}
public class DecoratorB extends Decorator {
public DecoratorB(Component component) {
super(component);
// TODO Auto-generated constructor stub
}
@Override
public void operation() {
// TODO Auto-generated method stub
addtionalOperationB();
this.component.operation();
}
public void addtionalOperationB() {
System.out.println("addtionalOperationB");
}
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Component component = new ConcreteComponent();
//开始装饰
component = new DecoratorA(component);
component.operation();//仅仅被A装饰
System.out.println("======");
component = new DecoratorB(component);
component.operation();//被B A同时装饰
}
}
References
- 《设计模式:可复用面向对象软件的基础》