102、23种设计模式之装饰器模式(11/23)

一、定义

装饰器模式(Decorator Pattern)是一种结构型设计模式,允许在不修改原有类或继承体系的前提下,动态地为对象添加新功能。其核心思想是通过组合而非继承实现功能扩展,符合"开闭原则"(对扩展开放,对修改关闭)。

二、应用场景

1.动态扩展功能

需要运行时为对象灵活添加/移除功能,例如:

  • 为文本编辑器动态添加字体、颜色、下划线等格式。
  • 为咖啡店饮品动态添加配料(牛奶、糖浆等)。

2.避免继承导致的类爆炸

当继承会导致子类数量指数级增长时(如为每个功能组合创建子类),装饰器模式通过组合实现功能排列组合。

3.需要透明扩展的场景

客户端无需知道对象是否被装饰,接口保持一致(如Java IO流中的BufferedInputStream装饰FileInputStream)。

4.替代多层继承

如Android中为View动态添加边框、点击事件等,避免继承导致的层次过深。

三、优缺点

1.优点

  1. 灵活性高:动态添加/移除功能,无需修改原有代码。
  2. 避免类爆炸:通过组合实现功能扩展,减少子类数量。
  3. 符合开闭原则:对扩展开放,对修改关闭。

2.缺点

  1. 代码复杂度增加:多层装饰时,调试和追踪逻辑困难。
  2. 性能开销:多层装饰可能增加对象创建和调用的开销。
  3. 接口污染风险:装饰器需实现与被装饰对象相同的接口,可能暴露不必要的方法。

四、C# 示例代码

以下示例模拟为Person对象动态添加"红帽子"和"黑外套"装饰:

csharp 复制代码
using System;

// 1. 定义组件接口
public interface IPerson
{
    void Introduce();
}

// 2. 具体组件:原始对象
public class Person : IPerson
{
    private string _name;
    private int _age;

    public Person(string name, int age)
    {
        _name = name;
        _age = age;
    }

    public void Introduce()
    {
        Console.WriteLine($"我叫{_name},今年{_age}岁");
    }
}

// 3. 抽象装饰器:持有组件引用
public abstract class PersonDecorator : IPerson
{
    protected IPerson _person;

    public PersonDecorator(IPerson person)
    {
        _person = person;
    }

    public virtual void Introduce()
    {
        _person.Introduce();
    }
}

// 4. 具体装饰器:红帽子
public class PersonRedHatDecorator : PersonDecorator
{
    public PersonRedHatDecorator(IPerson person) : base(person) { }

    public override void Introduce()
    {
        base.Introduce();
        Console.WriteLine("我有一顶红色的帽子");
    }
}

// 5. 具体装饰器:黑外套
public class PersonBlackJacketDecorator : PersonDecorator
{
    public PersonBlackJacketDecorator(IPerson person) : base(person) { }

    public override void Introduce()
    {
        base.Introduce();
        Console.WriteLine("我有一件黑色的外套");
    }
}

// 6. 客户端代码
class Program
{
    static void Main(string[] args)
    {
        // 原始对象
        IPerson person = new Person("张三", 18);
        person.Introduce();

        Console.WriteLine("---------装饰上红帽子---------");
        person = new PersonRedHatDecorator(person);
        person.Introduce();

        Console.WriteLine("---------装饰上黑外套---------");
        person = new PersonBlackJacketDecorator(person);
        person.Introduce();
    }
}

输出结果:

csharp 复制代码
我叫张三,今年18岁
---------装饰上红帽子---------
我叫张三,今年18岁
我有一顶红色的帽子
---------装饰上黑外套---------
我叫张三,今年18岁
我有一顶红色的帽子
我有一件黑色的外套

五、关键点总结

  1. 装饰器与被装饰对象实现相同接口,确保客户端代码无感知。
  2. 装饰器持有被装饰对象的引用,通过组合实现功能叠加。
  3. 支持多层装饰,如示例中先添加红帽子,再添加黑外套。
  4. 典型应用:Java IO流、ASP.NET Core中间件、GUI组件扩展等。
相关推荐
杨充20 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充20 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充20 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充20 小时前
2.面向对象的特性
设计模式
杨充20 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充20 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充21 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式