装饰器模式(Decorator Pattern)是一种结构型设计模式,允许你动态地给一个对象添加额外的职责。装饰器模式通常用于在不改变对象本身的情况下,给对象增加新的行为。
关键点:
- Component:定义一个接口,可以是抽象类或接口。
- ConcreteComponent :实现了
Component
接口的具体类。 - Decorator :继承自
Component
,并持有一个Component
实例,用于在此基础上增加额外的行为。 - ConcreteDecorator :继承自
Decorator
,并可以在装饰器中添加具体的功能。
示例代码
下面是一个简单的装饰器模式实现示例,模拟了为 Drink
类添加不同的"配料"来增强饮品的功能。
1. 定义 Drink
接口和实现类
cs
// 抽象基类
public interface IDrink
{
double Cost(); // 计算饮品的价格
string Description(); // 获取饮品描述
}
// 具体的饮品
public class Coffee : IDrink
{
public double Cost() => 5.0;
public string Description() => "Coffee";
}
public class Tea : IDrink
{
public double Cost() => 3.0;
public string Description() => "Tea";
}
2. 定义装饰器类
cs
// 装饰器基类,继承自 IDrink 并包含对 IDrink 的引用
public abstract class DrinkDecorator : IDrink
{
protected IDrink _drink;
public DrinkDecorator(IDrink drink)
{
_drink = drink;
}
public virtual double Cost() => _drink.Cost(); // 默认返回基础饮品的价格
public virtual string Description() => _drink.Description(); // 默认返回基础饮品的描述
}
3. 创建具体的装饰器类
cs
// 添加牛奶的装饰器
public class MilkDecorator : DrinkDecorator
{
public MilkDecorator(IDrink drink) : base(drink) { }
public override double Cost() => _drink.Cost() + 1.5; // 添加牛奶的价格
public override string Description() => _drink.Description() + ", Milk"; // 添加描述
}
// 添加糖的装饰器
public class SugarDecorator : DrinkDecorator
{
public SugarDecorator(IDrink drink) : base(drink) { }
public override double Cost() => _drink.Cost() + 0.5; // 添加糖的价格
public override string Description() => _drink.Description() + ", Sugar"; // 添加描述
}
4. 使用装饰器
cs
class Program
{
static void Main(string[] args)
{
// 创建基础饮品
IDrink myCoffee = new Coffee();
Console.WriteLine($"Description: {myCoffee.Description()}, Cost: {myCoffee.Cost()}");
// 装饰饮品,添加牛奶
myCoffee = new MilkDecorator(myCoffee);
Console.WriteLine($"Description: {myCoffee.Description()}, Cost: {myCoffee.Cost()}");
// 再装饰,添加糖
myCoffee = new SugarDecorator(myCoffee);
Console.WriteLine($"Description: {myCoffee.Description()}, Cost: {myCoffee.Cost()}");
// 输出:添加了牛奶和糖后的最终饮品
Console.WriteLine($"Final Description: {myCoffee.Description()}, Final Cost: {myCoffee.Cost()}");
}
}
输出结果:
cs
Description: Coffee, Cost: 5
Description: Coffee, Milk, Cost: 6.5
Description: Coffee, Milk, Sugar, Cost: 7
Final Description: Coffee, Milk, Sugar, Final Cost: 7
解释:
- 基础饮品 :我们首先创建了一个
Coffee
对象,其基础价格为 5. - 装饰器 :然后通过
MilkDecorator
和SugarDecorator
为这个饮品添加了额外的配料(牛奶和糖)。 - 最终结果:最终,我们得到了一个描述为"Coffee, Milk, Sugar"的饮品,并且总价格是 7.
通过装饰器模式,我们可以动态地添加或删除行为,而不需要修改原有的类结构。这个模式非常适用于需要在运行时根据需要扩展对象行为的场景。