0%

装饰器模式

装饰器模式(Decorator Pattern):动态扩展对象功能的灵活方式

装饰器模式是结构型设计模式的一种,核心思想是动态地给对象添加额外职责或功能,而无需修改原对象的结构。它通过 “包装”(组合)而非 “继承” 实现扩展,比生成子类更灵活,本质是 “动态组合”。

装饰器模式的核心结构

装饰器模式通过四个角色实现功能的动态扩展,层次清晰且职责明确:

组件接口(Component)

  • 定义对象的核心功能接口,是装饰器和具体组件的共同父类。
  • 示例:InputStream(Java IO 中的输入流接口,定义读取数据的核心方法)。

具体组件(ConcreteComponent)

  • 实现组件接口,是被装饰的原始对象,提供基础功能。
  • 示例:FileInputStream(具体的文件输入流,实现基础的文件读取)。

装饰器抽象类(Decorator)

  • 实现组件接口,并持有一个组件对象的引用(通过构造方法注入),定义所有装饰器的统一接口。
  • 示例:FilterInputStream(Java IO 中的装饰器抽象类,持有InputStream引用)。

具体装饰器(ConcreteDecorator)

  • 继承装饰器抽象类,添加额外功能,在调用被装饰对象的方法前后插入新逻辑。
  • 示例:BufferedInputStream(为输入流添加缓冲功能)、DataInputStream(添加数据类型转换功能)。

代码实现示例

以 “咖啡订单系统” 为例:基础咖啡(如美式咖啡)可通过装饰器动态添加牛奶、糖等配料,实现功能扩展。

1. 组件接口与具体组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 1. 组件接口(咖啡)
interface Coffee {
String getDescription(); // 获取描述
double getCost(); // 获取价格
}

// 2. 具体组件(美式咖啡,基础款)
class Americano implements Coffee {
@Override
public String getDescription() {
return "美式咖啡";
}
@Override
public double getCost() {
return 20.0; // 基础价格
}
}

2. 装饰器抽象类与具体装饰器

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
// 3. 装饰器抽象类(咖啡配料装饰器)
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee; // 持有被装饰的咖啡对象

// 通过构造方法注入被装饰对象
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
}

// 4. 具体装饰器1(加牛奶)
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}

@Override
public String getDescription() {
// 扩展描述:在原有基础上添加“加牛奶”
return coffee.getDescription() + " + 牛奶";
}

@Override
public double getCost() {
// 扩展价格:原有价格 + 牛奶的5元
return coffee.getCost() + 5.0;
}
}

// 5. 具体装饰器2(加糖)
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}

@Override
public String getDescription() {
return coffee.getDescription() + " + 糖";
}

@Override
public double getCost() {
return coffee.getCost() + 2.0; // 糖的价格2元
}
}

3. 客户端使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class DecoratorDemo {
public static void main(String[] args) {
// 基础咖啡:美式咖啡
Coffee coffee = new Americano();
System.out.println(coffee.getDescription() + ",价格:" + coffee.getCost()); // 美式咖啡,价格:20.0

// 装饰1:加牛奶
Coffee milkCoffee = new MilkDecorator(coffee);
System.out.println(milkCoffee.getDescription() + ",价格:" + milkCoffee.getCost()); // 美式咖啡 + 牛奶,价格:25.0

// 装饰2:再加糖(多次装饰)
Coffee milkSugarCoffee = new SugarDecorator(milkCoffee);
System.out.println(milkSugarCoffee.getDescription() + ",价格:" + milkSugarCoffee.getCost()); // 美式咖啡 + 牛奶 + 糖,价格:27.0
}
}

经典应用:Java IO 中的装饰器模式

Java IO 框架广泛使用装饰器模式,通过不同的装饰器组合实现多样的输入输出功能:

1
2
3
4
5
6
7
8
9
10
11
// 具体组件:文件输入流(基础功能)
InputStream fileIn = new FileInputStream("data.txt");

// 装饰器1:添加缓冲功能(提高读取效率)
InputStream bufferedIn = new BufferedInputStream(fileIn);

// 装饰器2:添加数据类型转换功能(如读取int、double)
DataInputStream dataIn = new DataInputStream(bufferedIn);

// 调用装饰后的功能
int num = dataIn.readInt(); // 兼具文件读取、缓冲、数据转换功能
  • 组件接口InputStream(定义read()等核心方法)。
  • 具体组件FileInputStreamByteArrayInputStream(基础输入流)。
  • 装饰器抽象类FilterInputStream(持有InputStream引用)。
  • 具体装饰器BufferedInputStream(缓冲)、DataInputStream(数据转换)、CheckedInputStream(校验和)等。

装饰器模式的核心优势

  1. 动态扩展功能
    可在运行时为对象添加或移除功能(如咖啡可随时加 / 不加牛奶),无需修改原始类,符合开闭原则。
  2. 灵活组合功能
    通过多个装饰器的嵌套组合,实现复杂功能(如 “缓冲 + 数据转换 + 校验” 的输入流),组合方式远超继承的灵活性。
  3. 避免类爆炸
    若用继承实现功能扩展(如MilkAmericanoSugarAmericanoMilkSugarAmericano),会导致类数量急剧增加,而装饰器模式通过组合解决这一问题。
  4. 单一职责原则
    每个装饰器仅负责添加一种功能(如MilkDecorator只处理牛奶),职责清晰,便于维护和复用。

优缺点分析

优点

  • 扩展性强:无需修改原有代码,通过新增装饰器即可扩展功能。
  • 灵活性高:可任意组合装饰器,实现不同功能组合。
  • 低耦合:具体组件与装饰器独立变化,互不影响。

缺点

  • 对象层次复杂:多层装饰会导致对象嵌套层次深(如A(B(C(original)))),调试和理解难度增加。
  • 过度设计风险:简单扩展场景使用装饰器可能显得繁琐(如仅需添加一个固定功能,继承可能更简单)。

适用场景

  1. 需要动态扩展对象功能
    如 IO 流的缓冲、加密、压缩等功能,需根据场景灵活组合。
  2. 避免使用继承扩展
    当功能组合过多(如 10 种配料的咖啡),继承会导致类爆炸,装饰器是更好选择。
  3. 扩展不可继承的类
    若被扩展的类是final(不可继承),只能通过装饰器实现扩展。
  4. 功能需随时开启 / 关闭
    如日志系统可动态开启 / 关闭 “时间戳”“线程名” 等附加信息。

总结

装饰器模式通过 “动态组合” 实现对象功能的灵活扩展,核心是 “包装原有对象,添加新逻辑”。它弥补了继承的静态性缺陷,尤其适合需要多种功能组合的场景(如 Java IO)。使用时需注意控制装饰层次,避免过度复杂

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10