结构性模式之装饰器模式
结构型模式:把类或对象结合在一起形成一个更大的结构。
概念
所谓装饰器模式,就是动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
使用场景:
- 当我们需要在不影响其他类的状况下,以动态、透明的方式为类添加功能;
- 当不适合使用继承,又想进行方法扩展的时候;
结构
image.png-
1.Component抽象构件:
Component是一个接口或者一个抽象类,就是定义我们最核心的对象,也就是最原始的对象,最高层次的抽象,统一整个装饰器系统,用于装饰器之间沟通的桥梁,就像II/O流中的InputStream,OutputStream一样 -
2.ConcreteComponent具体构件
ConcreteComponent是最核心,最原始,最基本的接口或者抽象类的实现,你要装饰的就是它,装饰的源头,你装饰的最底层,就像I/O流一样,这就直接跟底层打交道的节点流,就比如FileInputStream -
3.Decorator 装饰角色
一般是一个抽象类,实现接口或者抽象方法,它并不一定有抽象方法,但在它的属性里必须有一个private变量指向Component抽象构件,一般是用构造器初始化。就像I/O流中的FilterInputStream -
4.ConcreteDecoratorA,ConcreteDecoratorB具体的装饰器角色,这就是要将我们之间建的最核心,最原始,最基础的东西装饰成东西或者其他的东西,就像I/O中的BufferedInputStream,DataInputStream等。
使用实例——Java I/O
由于java I/O库需要很多性能的各种组合,如果这些性能都是用继承来实现,那么每一种组合都需要一个类,这样就会造成大量行重复的类出现。如果采用装饰模式,那么类的数目就会大大减少,性能的重复也可以减至最少。因此装饰模式是java I/O库基本模式。装饰模式的引进,造成灵活性和复杂性的提高。因此在使用 java I/O 库时,必须理解java I/O库是由一些基本的原始流处理器和围绕它们的装饰流处理器所组成的。
image.pngInputStream类是以抽象组件的形式存在,而FileInputStream就是具体组件,它实现了抽象接口的所有方法,并且持有InputStream对象的引用。FilterInputStream就是一个装饰类,而BufferInputStream是这个装饰类的具体实现者,它给InputStream加入了新的功能,使得InputStream读取的数据保存在内存中,从而提高读取性能。
更详细的类图关系如下,左半部分是InputStream的装饰体系,右半部分是Reader的装饰体系,并且他们之间的桥梁是InputStreamReader,他们每一个装饰体系都与上面标准的装饰器模式类图很相似。
image.png总之,装饰器模式就是一个可以非常灵活的动态扩展类功能的设计模式,它采用组合的方式取代继承,使得各个功能的扩展更加独立和灵活。
举一个工作中的实例,在别的模块有一个数据处理的接口类,我们需要对其进行功能扩展(扩展一些排序,去重的的功能),但是又不想直接继承其实现类,因为我们只需要用到其中的一些方法和属性,同时我们自己也有大量的方法和属性,如果继承会造成冗余。这时我们就可以使用装饰器模式,新建一个抽象类,实现数据处理接口,同时有一个private变量指向数据处理的接口类变量,然后我们就可以根据我们自己的需求对齐进行功能扩展,而不用改变/继承原有的类。