8、装饰器模式
8.1 装饰器模式(Decorator)
- 能够在运行时动态地为原始对象增加一些额外的功能
- 装饰器非常类似于“继承”,它们都是为了增强原始对象的功能,区别在于方式的不同
- 后者是在编译时(compile-time)静态地通过对原始类的继承完成
- 前者则是在程序运行时(run-time)通过对原始对象动态地“包装”完成,是对类实例(对象)“装饰”的结果
- 测试类结构
![装饰器测试类结构](https://i-blog.csdnimg.cn/direct/d74231b24d034deca2f74345d71b527c.png)
8.2 装修(举例)
- 不改变其原始结构的前提下使客体功能得到扩展、增强
- 以室内装潢为例
- 装修风格多种多样
- 朴素的毛坯房能给业主留有更大的装修选择空间,以根据自己的喜好进行二次加工
- 成品一定是由半成品加工而成的
- 灵活多变的装饰才会带来更多的可能,因此装饰器模式应运而生
8.3 化妆(示例)
- 首先对于任何妆容展示者必然对应一个标准的展示行为show()
- 我们将它抽象出来定义为接口Showable
- Showable这个标准行为需要人去实现,定义女生类,素颜展示
- 如果客户端直接调用show()方法,就会出现素面朝天的结果
package decorator;
public interface Showable {
public void show();
}
- 化妆品我们在这里称为“装饰器”: 化妆品装饰器类Decorator
package decorator.base;
import decorator.Showable;
public class Decorator implements Showable {
Showable showable;
public Decorator(Showable showable) {
this.showable = showable;
}
@Override
public void show() {
System.out.print("粉饰【");
showable.show();
System.out.print("】");
}
}
package decorator.entity;
import decorator.Showable;
public class Girl implements Showable {
@Override
public void show() {
System.out.print("女生的素颜");
}
}
package decorator.base;
import decorator.entity.Girl;
public class Client {
public static void main(String[] args) {
new Decorator(new Girl()).show();
}
}
8.4 化妆品的多样化
package decorator.ab;
import decorator.entity.Girl;
import decorator.Showable;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.zip.ZipInputStream;
public class Client {
public static void main(String[] args) throws FileNotFoundException {
test1();
test2();
}
private static void test1() {
Girl girl = new Girl();
Showable foundationMakeup = new FoundationMakeup(girl);
Showable medeupGirl = new Lipstick(foundationMakeup);
medeupGirl.show();
}
private static void test2() throws FileNotFoundException {
File file = new File("/压缩包.zip");
ZipInputStream zipInputStream = new ZipInputStream(
new BufferedInputStream(
new FileInputStream(file)
)
);
}
}
8.5 装饰器
- 如同“俄罗斯套娃”一般层层嵌套
- 其实装饰器模式在Java开发工具包(Java Development Kit,JDK)里就有大量应用
- 例如“java.io”包里一系列的流处理类InputStream、FileInputStream、BufferedInputStream、ZipInputStream等
- 举个例子,当对压缩文件进行解压操作时,我们就会用构造器嵌套结构进行文件流装饰,如:ab.Client.test2()
8.6 自由嵌套
- 装饰器模式最终的目的就在于“装饰”对象
- 其中装饰器抽象类扮演着至关重要的角色,它实现了组件的通用接口
- 并且使自身抽象化以迫使子类继承,使装饰器固定特性的延续与多态化成为可能
8.7 装饰器模式的各角色定义
- Component(组件接口):
- 所有被装饰组件及装饰器对应的接口标准,指定进行装饰的行为方法。如:展示接口Showable。
- ConcreteComponent(组件实现):
- 需要被装饰的组件,实现组件接口标准,只具备自身未被装饰的原始特性。如:类Girl
- Decorator(装饰器):
- 装饰器的高层抽象类,
- 同样实现组件接口标准,且包含一个被装饰的组件
- ConcreteDecorator(装饰器实现)
- 继承自装饰器抽象类的具体子类装饰器,可以有多种实现,在被装饰组件对象的基础上为其添加新的特性
- 如: 粉底类FoundationMakeup、口红类Lipstick
8.8 装饰器模式
- 装饰器模式可以将不同功能的单个模块规划至不同的装饰器类中
- 客户端可以根据自己的需求自由搭配各种装饰器,每加一层装饰就会有新的特性体现出来
- 最终使原始对象的特性动态地得到增强