装饰器模式
# 一、概述
装饰器(Decorator)模式,也叫包装器(Wrapper)模式,可以动态地给一个对象增加一些额外的职责,就增加功能来说,相比生成子类更加灵活。
# 1.1 解决了什么问题
还是用造车的那个问题举例。大家都知道传统燃油车的三大件:发动机、变速箱和地盘悬架。也就说说对于一辆燃油车而言,这三个是必须存在的。但是一些其它的配置(如:变道辅助、倒车雷达、ACC 自适应巡航、电尾门等)可能会由于品牌、车型、价位等可有可无,哪怕是同一品牌的同一款车,也可能会根据客户需求进行选装。
前面在建造者模式中使用这个例子,是因为是要从零开始构建一个对象,可以有规划地进行配置选装。
但是假设已经有一个汽车类了,其基本功能就只有三大件,而且这个类已经在系统中运行了很久了,现在想为其扩展一些配置。首先想到的就是通过子类继承的方式实现,但是这种方式存在一个问题,汽车的各种科技配置和舒适性配置有几十项(座椅通风、座椅加热、电动后视镜、方向盘加热、后视镜加热、自动感应大灯等),而为了满足客户个性化的定制需求,就需要使用各个配置做排列组合去实现一个个子类,这样的话就需要定义非常多的子类,这肯定是不能接受的。所以第一个问题就是需要定义的代码太多。
第二个问题是需要创建某个配置的车型,必须事先定义其子类,无法在运行时动态增加配置。
# 1.2 解决方案
创建一个装饰器类,装饰器类包含和目标对象相同的一系列方法,并将所有接收到的请求委派给目标对象。但是装饰器对象可以在将请求委派给目标对象之前和之后都对其进行处理,从而到达“包装”的效果。
# 二、实现方式
# 2.1 角色
- 通用部件类:申明装饰器和被装饰对象的公用接口。
- 具体部件类:即被装饰的实例类,其中定义了最基础的一些行为。
- 基础装饰类:拥有一个指向被封装对象的成员变量,该边浪类型为通用部件接口。
- 具体装饰类:定义可以动态添加到部件的额外行为,具体装饰类会重写基础装饰类的所有方法。
# 2.2 代码
通用部件接口:
interface Automobile {
// 配置清单
List<String> confList = new ArrayList<>();
void makeAutomobile();
}
1
2
3
4
5
6
2
3
4
5
6
具体部件类:
/**
* 基础汽车类
*/
class BaseAutomobile implements Automobile {
public BaseAutomobile() {
confList.add("2.0T Engine");
confList.add("双离合变速箱");
confList.add("承载式车身");
}
@Override
public void makeAutomobile() {
System.out.println(confList);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
基础装饰类:
class AutomobileDecorator implements Automobile {
public Automobile automobile;
public AutomobileDecorator(Automobile automobile) {
this.automobile = automobile;
}
@Override
public void makeAutomobile() {
automobile.makeAutomobile();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
具体装饰类:
/**
* ACC功能装饰器
*/
class AccDecorator extends AutomobileDecorator {
public AccDecorator(Automobile automobile) {
super(automobile);
}
@Override
public void makeAutomobile() {
this.setAcc();
System.out.println(confList);
}
private void setAcc() {
confList.add("acc");
}
}
/**
* 倒车雷达装饰类
*/
class ReversingRadarDecorator extends AutomobileDecorator {
public ReversingRadarDecorator(Automobile automobile) {
super(automobile);
}
@Override
public void makeAutomobile() {
this.setReversingRadar();
System.out.println(confList);
}
public void setReversingRadar() {
confList.add("reversingRadar");
}
}
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
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
示例:
public class DecoratorTest {
public static void main(String[] args) {
Automobile automobile = new BaseAutomobile();
automobile.makeAutomobile();
automobile = new AccDecorator(automobile);
automobile.makeAutomobile();
automobile = new ReversingRadarDecorator(automobile);
automobile.makeAutomobile();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
[2.0T Engine, 双离合变速箱, 承载式车身]
[2.0T Engine, 双离合变速箱, 承载式车身, acc]
[2.0T Engine, 双离合变速箱, 承载式车身, acc, reversingRadar]
1
2
3
2
3
# 三、源码中的应用
- java.io.BufferedInputStream(InputStream)
- java.io.DataInputStream(InputStream)
- java.io.BufferedOutputStream(OutputStream)
上次更新: 2023/11/01, 03:11:44