编辑
2025-09-28
C#
00

目录

摘要
正文
结构组成
优点
缺点
示例:咖啡店订单系统

摘要

装饰模式的核心在于,它允许在不改变对象自身的基础上,在运行时向对象添加新的职责。这是通过创建一个包含原始对象的特殊包装对象(即装饰器)来实现的。装饰器类遵循与原始对象相同的接口,并在调用原始对象的方法之前或之后添加额外的行为。

正文

结构组成

装饰模式通常由以下几个角色组成:

  • 抽象组件 (Component):定义一个对象接口,可以给这些对象动态地添加职责。
  • 具体组件 (ConcreteComponent):定义了一个具体的对象,也可以给这个对象添加一些职责。
  • 装饰抽象类 (Decorator):实现了组件接口的同名接口,并持有一个组件实例的引用。这个类的任务是定义一个与组件接口一致的接口。
  • 具体装饰类 (ConcreteDecorator):具体实现装饰抽象类,其目的是给组件添加额外的职责。

优点

装饰模式的优点包括:

  • 增加对象的职责是灵活的。
  • 可以动态地添加或删除职责。
  • 可以用多个装饰类包装一个对象来组合几个行为。
  • 装饰模式是继承的一种替代模式,可以动态扩展一个实现类的功能。

缺点

装饰模式的缺点包括:

  • 使用装饰模式会创建更多的小对象,可能会导致系统更加复杂。
  • 装饰链设置不当可能会导致调试问题。

装饰模式在.NET框架中也有广泛的应用,例如在IO流的处理中,StreamReaderStreamWriter就是Stream的装饰器,它们提供了缓冲和字符处理的功能。通过这种方式,.NET框架能够提供高度灵活和可扩展的读写功能。

示例:咖啡店订单系统

假设我们有一个咖啡店的订单系统,我们需要能够动态地给咖啡添加各种配料,比如牛奶、糖、奶泡等。

首先,我们定义咖啡的组件接口:

C#
// 组件接口 public interface ICoffee { string GetDescription(); double GetCost(); }

然后,我们实现具体的咖啡类型:

C#
// 具体组件 public class PlainCoffee : ICoffee { public string GetDescription() { return "Plain Coffee"; } public double GetCost() { return 1.0; } }

接下来,我们创建一个装饰器抽象类:

C#
// 装饰抽象类 public abstract class CoffeeDecorator : ICoffee { protected ICoffee _coffee; public CoffeeDecorator(ICoffee coffee) { _coffee = coffee; } public virtual string GetDescription() { return _coffee.GetDescription(); } public virtual double GetCost() { return _coffee.GetCost(); } }

现在,我们可以创建具体的装饰类:

C#
// 具体装饰类:牛奶 public class MilkDecorator : CoffeeDecorator { public MilkDecorator(ICoffee coffee) : base(coffee) { } public override string GetDescription() { return base.GetDescription() + ", with Milk"; } public override double GetCost() { return base.GetCost() + 0.5; } }
C#
// 具体装饰类:糖 public class SugarDecorator : CoffeeDecorator { public SugarDecorator(ICoffee coffee) : base(coffee) { } public override string GetDescription() { return base.GetDescription() + ", with Sugar"; } public override double GetCost() { return base.GetCost() + 0.2; } }

最后,我们可以使用装饰模式来创建订单:

C#
public class Program { public static void Main() { ICoffee coffee = new PlainCoffee(); Console.WriteLine($"{coffee.GetDescription()} Cost: ${coffee.GetCost()}"); // 添加牛奶 coffee = new MilkDecorator(coffee); Console.WriteLine($"{coffee.GetDescription()} Cost: ${coffee.GetCost()}"); // 再添加糖 coffee = new SugarDecorator(coffee); Console.WriteLine($"{coffee.GetDescription()} Cost: ${coffee.GetCost()}"); } }

image.png

在这个例子中,我们首先创建了一个简单的咖啡对象,然后通过添加装饰器(牛奶和糖)来增加额外的功能(调料),同时每次装饰都会影响咖啡的最终成本。这种方式使得我们可以动态地、不限次数地添加新的装饰器,而不需要修改现有的类。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!