C#设计模式实战:生成器与责任链模式的实现
本文深入解析C#中的两种常用设计模式:生成器模式与责任链模式。通过构建度假计划和邮件处理的实际案例,详细展示了如何利用生成器模式分步构造复杂对象以封装创建过程,以及如何通过责任链模式解耦请求发送者与接收者,实现链式处理逻辑。
生成器模式
生成器模式(Builder Pattern)的核心在于将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。其关键在于封装产品的构造步骤,允许按特定顺序逐步完成对象的初始化。
假设我们需要为一个旅行应用构建“度假计划”数据结构。每位游客的行程安排差异巨大,涉及天数、旅馆、景点、活动和餐饮等多个维度。如果采用传统构造函数一次性传入所有参数,不仅参数列表冗长,且难以处理可选属性或缺省值。因此,我们将旅游规划的创建过程封装在一个独立的“生成器”对象中,由客户按需调用不同方法来填充数据。
设计思路
我们采用抽象生成器定义构建步骤的接口,再由具体生成器实现这些步骤。这种设计将复杂的组装逻辑隐藏在内部,对外只暴露简洁的调用方式。
C# 代码实现
首先定义用于存储数据的 Vacation 类:
public class Vacation
{
public int Day { get; set; }
public string Hotel { get; set; }
public string Park { get; set; }
public string Activity { get; set; }
public string Meal { get; set; }
}
接着定义抽象生成器 AbstractBuilder,规定必须实现的构建方法:
public abstract class AbstractBuilder
{
public abstract void BuildDay(int day);
public abstract void Hotel(string hotel);
public abstract void Park(string park);
public abstract void Activity(string activity);
public abstract void Meal(string meal);
public abstract Vacation GetVacationPlanner();
}
然后实现具体的生成器 VacationBuilder,负责将步骤应用于实际对象:
public class VacationBuilder : AbstractBuilder
{
private Vacation vacation = new Vacation();
public override void BuildDay(int day)
{
vacation.Day = day;
}
public override void Hotel(string hotel)
{
vacation.Hotel = hotel;
}
public override void Activity(string activity)
{
vacation.Activity = activity;
}
public override void Meal(string meal)
{
vacation.Meal = meal;
}
public override void Park(string park)
{
vacation.Park = park;
}
public override Vacation GetVacationPlanner()
{
return vacation;
}
}
最后,客户端可以通过链式调用或直接调用来使用生成器:
var builder = new VacationBuilder();
builder.BuildDay(1);
builder.Hotel("Grand Hotel");
builder.Park("Disneyland");
// ... 其他步骤
Vacation plan = builder.GetVacationPlanner();
生成器模式的优点
- 封装复杂性:将复杂对象的创建过程和表示隔离,隐藏了内部的构建细节。
- 灵活的控制:允许客户通过改变构建过程的顺序或步骤来创建不同的产品。
- 隐藏内部表现:客户端无需了解产品内部结构的具体实现。
- 替换实现:只要遵循抽象接口,就可以轻松替换具体的生成器实现。
局限性与适用场景
- 适用场景:常用于创建具有多个组成部分或需要按特定顺序构建的组合型对象。
- 局限性:相比于工厂模式,客户端需要更深入了解领域知识才能正确指挥构建过程;若产品变化极小,则可能显得过于复杂。
责任链模式
责任链模式(Chain of Responsibility Pattern)旨在避免请求发送者与接收者之间的耦合。它使多个对象都有机会处理请求,将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
以一个公司邮件处理系统为例:接收到的邮件需要根据类型分发。个人邮件由收件人直接处理,工作邮件转发给经理,垃圾邮件则由系统自动删除。如果使用多重 if-else 判断,每当新增一种邮件类型时都需要修改核心代码。而责任链模式允许动态地增加或移除处理节点。
C# 代码实现
首先定义一个枚举来表示邮件类型,以及抽象的处理者基类:
/// <summary>
/// 邮件类型
/// </summary>
public enum EmailType
{
Self = 1,
Manager = 2,
Del = 3
}
public abstract class Handler
{
public Handler nextHandler;
public EmailType type;
public Handler(EmailType type) {
this.type = type;
}
public void SetNextHandler(Handler nextHandler)
{
this.nextHandler = nextHandler;
}
public abstract void HandleRequest(EmailType requsetType);
}
接下来实现具体的处理者,例如处理个人邮件的 SelfHandler:
class SelfHandler : Handler
{
public SelfHandler() : base(EmailType.Self) { }
public override void HandleRequest(EmailType requsetType)
{
if (EmailType.Self == requsetType)
{
Console.WriteLine("邮件由自己处理");
}
else
{
if (nextHandler != null)
{
nextHandler.HandleRequest(requsetType);
}
}
}
}
同理实现经理处理者 ManagerHandler 和垃圾邮件删除者 DelHandler:
class ManagerHandler : Handler
{
public ManagerHandler() : base(EmailType.Manager) { }
public override void HandleRequest(EmailType requsetType)
{
if (EmailType.Manager == requsetType)
{
Console.WriteLine("邮件转到经理处理");
}
else
{
if (nextHandler != null)
{
nextHandler.HandleRequest(requsetType);
}
}
}
}
class DelHandler : Handler
{
public DelHandler() : base(EmailType.Del) { }
public override void HandleRequest(EmailType requsetType)
{
if (EmailType.Del == requsetType)
{
Console.WriteLine("垃圾邮件已删除");
}
else
{
if (nextHandler != null)
{
nextHandler.HandleRequest(requsetType);
}
}
}
}
在客户端组装责任链并进行测试:
class Program
{
static void Main(string[] args)
{
// 1. 组装责任链
Handler selfHandler = new SelfHandler();
Handler managerHandler = new ManagerHandler();
Handler delHandler = new DelHandler();
selfHandler.SetNextHandler(managerHandler);
managerHandler.SetNextHandler(delHandler);
// 2. 发起请求测试
Console.WriteLine("--- 测试流程 ---");
selfHandler.HandleRequest(EmailType.Del); // 应该输出: 垃圾邮件已删除
selfHandler.HandleRequest(EmailType.Manager); // 应该输出: 邮件转到经理处理
selfHandler.HandleRequest(EmailType.Self); // 应该输出: 邮件由自己处理
Console.ReadKey();
}
}
责任链模式的优点
- 解耦发送者与接收者:发送请求的对象只需将请求发给链首,无需关心谁最终处理。
- 简化对象:对象无需知道链的结构,只需关注自己的处理逻辑。
- 动态扩展:可以随时调整链的成员顺序,或动态新增/删除特定的责任节点。
局限性与适用场景
- 适用场景:常用于窗口系统的事件处理(如鼠标、键盘事件)、权限验证流程、日志过滤等需要按顺序或条件流转的场景。
- 局限性:不保证请求一定被处理(若链尾未处理则可能被丢弃);调试时不易追踪整个链条的执行状态;若链条过长可能影响性能。
总结
生成器模式侧重于构造处理,通过链式传递实现请求的分发与解耦。在实际的C#开发中,理解这两种模式的适用边界,能够帮助你写出更清晰、易维护的业务逻辑代码。以上就是C#设计模式中生成器模式和责任链模式的详细内容,更多关于C#进阶实践的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









