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组件扩展等。
相关推荐
Zane199411 小时前
策略模式现在该不该上?一次讲清楚过度设计和设计不足怎么找平衡
设计模式
她说..12 小时前
常见设计模式-模板方法模式
java·spring·设计模式·springboot
xiaofeiyang1501 天前
第六章 · 桥接 — 三支毛笔,画出九种颜色
设计模式
Shadow(⊙o⊙)1 天前
OTOL设计模式 One Thread One Loop
服务器·网络·设计模式
sarasuki2 天前
如何让LLM 能在半夜偷偷打开网易云呢?
人工智能·设计模式·agent
小王师傅662 天前
【设计模式】装饰模式(四):框架源码实战——从 Java I/O 到 Spring 到 MyBatis
java·设计模式
执明wa2 天前
Android RecyclerView 多类型, 多种 Item
android·xml·开发语言·设计模式·android studio
sarasuki2 天前
如何让 Agent 获取更多的能力?插件 / 技能系统
人工智能·设计模式·agent
sarasuki2 天前
如何让 Agent 安全运行你的命令 :命令分级 + Hook + 读写锁
人工智能·设计模式·agent
Zane19942 天前
技术不难,为什么项目却越改越不敢动?聊聊复杂系统开发该怎么想
设计模式