C#中的装饰者模式

装饰者模式:动态扩展对象功能

主要代码:

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
46
47
48
49
50
51
52
53
54
55
public abstract class Beverage { 
public string description = "Unknown Beverage";

public virtual string GetDescription() {
return description;
}

public abstract float Cost();
}

public abstract class CondimentDecorator : Beverage {
// 装饰器基类
}

public class DerkBeverage : Beverage {
public DerkBeverage() {
description = "Derk Beverage";
}

public override float Cost() {
return 1.0f;
}
}

public class Milk : CondimentDecorator {
Beverage _beverage;

public Milk(Beverage beverage) {
_beverage = beverage;
}

public override string GetDescription() {
return _beverage.GetDescription() + ", Milk";
}

public override float Cost() {
return _beverage.Cost() + 0.1f;
}
}

public class Sugar : CondimentDecorator {
Beverage _beverage;

public Sugar(Beverage beverage) {
_beverage = beverage;
}

public override string GetDescription() {
return _beverage.GetDescription() + ", Sugar";
}

public override float Cost() {
return _beverage.Cost() + 0.1f;
}
}

模式结构

角色 代码示例 职责
组件接口 Beverage 定义基础对象接口
具体组件 DerkBeverage 实现基础功能
装饰器基类 CondimentDecorator 继承组件接口
具体装饰器 Milk/Sugar 添加额外功能

关键点

  1. 递归组合

    1
    2
    3
    4
    5
    6
    7
    public class Milk : CondimentDecorator {
    Beverage _beverage; // 持有被装饰对象

    public override float Cost() {
    return _beverage.Cost() + 0.1f; // 递归调用
    }
    }
  2. 透明装饰

    • 装饰器与组件接口一致

    • 客户端无感知装饰过程

  3. 动态扩展

    1
    2
    beverage = new Milk(beverage);  // 运行时添加功能
    beverage = new Sugar(beverage); // 可叠加多个装饰器

使用

1
2
3
4
5
6
7
8
Beverage beverage = new DerkBeverage();
Console.WriteLine(beverage.GetDescription() + " $" + beverage.Cost());

beverage = new Milk(beverage);
Console.WriteLine(beverage.GetDescription() + " $" + beverage.Cost());

beverage = new Sugar(beverage);
Console.WriteLine(beverage.GetDescription() + " $" + beverage.Cost());

优势分析

特性 实现方式 优势
动态扩展 运行时添加装饰器 避免静态继承的类爆炸
开闭原则 新增装饰器不影响现有代码 系统扩展性强
功能分解 每个装饰器只添加单一功能 符合单一职责原则
透明性 装饰器与组件接口一致 客户端无需改变调用方式

应用场景
- 需要动态添加/撤销功能

- 不适合使用子类扩展的场景

- 常见案例:

    - GUI组件装饰(滚动条/边框)

    - 流处理(加密/压缩装饰器)

    - 权限系统(叠加权限检查)

要点记忆:

  1. 所有装饰器继承CondimentDecorator基类

  2. 装饰器构造函数接收被装饰对象

  3. GetDescription()递归拼接描述

  4. Cost()递归计算总价

  5. 可多层嵌套装饰(牛奶+糖)