装饰器模式(Decorator Pattern)
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。装饰器模式通过创建一个装饰类来包裹原始类,从而在保持类接口不变的情况下增强对象的功能。
关键点
- 组件接口(Component Interface):定义一个对象接口,可以给这些对象动态地添加职责。
- 具体组件(Concrete Component):实现组件接口的基本对象。
- 装饰器(Decorator):实现组件接口,并持有一个组件对象的引用,通过组合的方式将原始对象的行为和新功能结合。
- 具体装饰器(Concrete Decorator):实现装饰器接口并添加额外的行为。
示例
假设我们有一个简单的文本显示组件,我们希望可以动态地向文本添加不同的装饰效果,比如加粗、斜体等。我们可以使用装饰器模式来实现这个需求。
1. 定义组件接口
csharp
// 组件接口 - 文本
public interface IText
{
void Display();
}
2. 实现具体组件
csharp
// 具体组件 - 普通文本
public class PlainText : IText
{
private string text;
public PlainText(string text)
{
this.text = text;
}
public void Display()
{
Console.WriteLine(text);
}
}
3. 创建装饰器
csharp
// 装饰器 - 基础装饰器
public abstract class TextDecorator : IText
{
protected IText decoratedText;
public TextDecorator(IText text)
{
decoratedText = text;
}
public virtual void Display()
{
decoratedText.Display();
}
}
4. 实现具体装饰器
csharp
// 具体装饰器 - 加粗文本
public class BoldText : TextDecorator
{
public BoldText(IText text) : base(text) { }
public override void Display()
{
Console.Write("<b>");
base.Display();
Console.Write("</b>");
}
}
// 具体装饰器 - 斜体文本
public class ItalicText : TextDecorator
{
public ItalicText(IText text) : base(text) { }
public override void Display()
{
Console.Write("<i>");
base.Display();
Console.Write("</i>");
}
}
5. 客户端代码
csharp
class Program
{
static void Main(string[] args)
{
IText plainText = new PlainText("Hello, World!");
// 使用加粗装饰器
IText boldText = new BoldText(plainText);
boldText.Display(); // 输出:<b>Hello, World!</b>
// 使用斜体装饰器
IText italicText = new ItalicText(plainText);
italicText.Display(); // 输出:<i>Hello, World!</i>
// 同时使用加粗和斜体装饰器
IText boldItalicText = new BoldText(new ItalicText(plainText));
boldItalicText.Display(); // 输出:<b><i>Hello, World!</i></b>
}
}
解释
- 组件接口(IText):定义了
Display
方法,这是所有文本组件和装饰器必须实现的方法。 - 具体组件(PlainText):实现了
IText
接口,提供基本的文本显示功能。 - 装饰器(TextDecorator):实现了
IText
接口,并持有一个IText
类型的成员变量,通过组合方式将原始文本对象的行为和新功能结合。 - 具体装饰器(BoldText 和 ItalicText):继承自
TextDecorator
,通过在Display
方法中增加新的行为来实现加粗和斜体的效果。
优点
- 职责单一原则:可以在不修改原始类的情况下向对象添加新功能。
- 开闭原则:可以通过创建新的具体装饰器来扩展对象的功能,而不需要修改已有代码。
- 灵活性:可以动态地组合不同的装饰器,从而实现多种功能的叠加。
缺点
- 复杂性增加:使用装饰器模式会增加系统中类的数量和复杂性,特别是在多个装饰器组合使用时。
- 创建装饰链:需要客户端代码显式地创建和组合装饰器对象,这可能会导致代码复杂且不易理解。
适用场景
- 需要动态地添加功能:在运行时需要向对象添加功能,而不影响其他对象。
- 功能扩展需求频繁变化:需要通过组合不同的功能来扩展对象,而不希望通过继承来实现。
- 避免类爆炸:如果通过继承来扩展功能会导致大量子类,可以使用装饰器模式来避免这种情况。