优秀的编程知识分享平台

网站首页 > 技术文章 正文

设计模式(C#) - 装饰器模式实现详解

nanyue 2025-04-30 18:37:42 技术文章 2 ℃

一、模式概述与核心思想

装饰器模式(Decorator Pattern)是一种动态扩展对象功能的结构型设计模式。其核心思想是通过组合而非继承的方式,在运行时为对象添加新功能,同时保持与原始接口的兼容性。该模式有效解决了传统继承机制导致的类层次结构臃肿问题,遵循开放-封闭原则——系统对功能扩展开放,但对已有代码修改关闭。典型应用场景包括流处理系统、UI组件增强以及需要动态配置功能的业务逻辑模块。

二、核心结构解析

装饰器模式包含四个关键角色:

  1. 组件接口(ITextProcessor):定义基础操作的抽象接口,作为被装饰对象和装饰器的共同契约
  2. 具体组件(PlainTextProcessor):实现组件接口的基础功能,即被装饰的原始对象
  3. 装饰器基类(TextProcessorDecorator):继承组件接口并持有组件实例的引用,通过委托机制实现功能传递
  4. 具体装饰器(ColorDecorator/BackgroundDecorator):继承装饰器基类,通过重写方法添加额外功能

这种结构使得装饰器与被装饰对象具有相同的接口,客户端无需区分基础对象与装饰后的对象。

三、接口与组件实现

首先定义核心接口声明文本处理方法,具体组件实现基础功能:

// 组件接口
public interface ITextProcessor
{
    string ProcessText(string input);
}

// 具体组件
public class PlainTextProcessor : ITextProcessor
{
    public string ProcessText(string input)
    {
        return input; // 返回原始文本
    }
}

基础组件仅完成最简单的文本传递,为后续装饰操作提供扩展起点。

四、装饰器基类设计

抽象装饰器类作为所有具体装饰器的父类,维护被装饰对象的引用并实现基础委托逻辑:

public abstract class TextProcessorDecorator : ITextProcessor
{
    protected ITextProcessor _textProcessor;

    protected TextProcessorDecorator(ITextProcessor textProcessor)
    {
        _textProcessor = textProcessor;
    }

    public virtual string ProcessText(string input)
    {
        // 默认行为:直接委托给被装饰对象
        return _textProcessor.ProcessText(input);
    }
}

虚方法设计允许子类在必要时重写核心逻辑,同时通过base调用保持基础功能链式传递。

五、具体装饰器实现

具体装饰器通过继承基类实现功能扩展。以下示例分别添加文本颜色和背景控制:

// 颜色装饰器
public class ColorDecorator : TextProcessorDecorator
{
    private readonly string _colorCode;

    public ColorDecorator(ITextProcessor textProcessor, string colorCode) 
        : base(textProcessor)
    {
        _colorCode = colorCode; // ANSI颜色代码
    }

    public override string ProcessText(string input)
    {
        var processed = base.ProcessText(input);
        return #34;\x1b[{_colorCode}m{processed}\x1b[0m"; // 添加颜色控制符
    }
}

// 背景装饰器
public class BackgroundDecorator : TextProcessorDecorator
{
    private readonly string _bgColorCode;

    public BackgroundDecorator(ITextProcessor textProcessor, string bgColorCode) 
        : base(textProcessor)
    {
        _bgColorCode = bgColorCode;
    }

    public override string ProcessText(string input)
    {
        var processed = base.ProcessText(input);
        return #34;\x1b[{_bgColorCode}m{processed}\x1b[0m"; // 包裹背景控制符
    }
}

每个装饰器仅关注单一功能扩展,通过base.ProcessText()调用保持处理链的连续性。

六、装饰器组合调用

客户端可通过嵌套装饰器实现功能叠加,以下示例创建带红色文字和蓝色背景的处理器:

var processor = new BackgroundDecorator(
    new ColorDecorator(
        new PlainTextProcessor(), 
        "31"), // ANSI红色前景
    "44"       // ANSI蓝色背景
);

var result = processor.ProcessText("Hello Decorator");
Console.WriteLine(result); 

执行后输出结果为带有ANSI转义码的字符串,在支持的控制台中显示为蓝底红字。装饰器嵌套顺序影响最终效果——内层装饰器的处理结果会被外层装饰器再次包装。

七、应用场景与优势分析

装饰器模式在以下场景中表现优异:

  • 动态功能扩展:需要运行时灵活添加或撤销对象功能
  • 多层功能叠加:多个独立扩展需要以不同组合方式应用
  • 替代多重继承:避免子类数量爆炸式增长

其核心优势体现在:

  1. 符合单一职责原则,每个装饰器只负责单一功能
  2. 支持功能动态组合,扩展性优于静态继承
  3. 避免修改已有代码,降低系统维护成本

在.NET生态中,System.IO.Stream及其装饰器(如BufferedStream、CryptoStream)是此模式的经典实现。理解装饰器模式有助于构建灵活、可维护的面向对象系统。

最近发表
标签列表