行为型设计模式2
职责链模式(Chain of Responsibility Pattern)是一种行为型设计模式,其核心思想是将多个处理对象连成一条链,请求沿着链传递,直到被某个对象处理。该模式通过解耦请求发送者与接收者,实现动态灵活的处理流程。模板方法模式(Template Method Pattern)是一种行为型设计模式,其核心思想是定义一个操作中的算法骨架,将某些步骤的具体实现延迟到子类中,使得子类在不改
·
文章目录
职责链模式👍
1、定义与核心思想
(1)定义
- 职责链模式(Chain of Responsibility Pattern)是一种行为型设计模式,其核心思想是将多个处理对象连成一条链,请求沿着链传递,直到被某个对象处理。该模式通过解耦请求发送者与接收者,实现动态灵活的处理流程。
(2)核心价值
- 降低耦合性:发送者无需知道具体处理者。
- 灵活扩展:可动态调整处理链的顺序或新增节点。
- 责任分离:每个处理者专注单一职责,符合单一职责原则。
2、模式结构与角色
(1)抽象处理者(Handler)
- 定义处理请求的接口,维护后继节点的引用
- 作用:统一处理逻辑,定义链式结构
public abstract class Handler
{
protected Handler successor;
public void SetSuccessor(Handler successor)
{
this.successor = successor;
}
public abstract void HandleRequest(int request);
}
(2)具体处理者(ConcreteHandler)
- 实现具体的处理逻辑,若无法处理则转发请求
- 关键点:通过条件判断决定是否处理请求
public class ConcreteHandlerA : Handler
{
public override void HandleRequest(int request)
{
if (request <= 1000)
{
Console.WriteLine("HandlerA处理请求:" + request);
}
else if (successor != null)
{
successor.HandleRequest(request); // 传递给下个节点
}
}
}
public class ConcreteHandlerB : Handler
{
public override void HandleRequest(int request)
{
if (request > 1000 && request <= 5000)
{
Console.WriteLine("HandlerB处理请求:" + request);
}
else
{
successor?.HandleRequest(request);
}
}
}
(3)客户端(Client)
- 构建处理链并触发请求:
public class Client
{
public static void Main()
{
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();
handlerA.SetSuccessor(handlerB);
handlerB.SetSuccessor(handlerC);
// 触发请求
int[] requests = { 500, 2500, 8000 };
foreach (var request in requests)
{
handlerA.HandleRequest(request);
}
}
}
- 输出示例:
HandlerA处理请求:500
HandlerB处理请求:2500
HandlerC处理请求:8000
- 作用:通过链式调用实现请求的动态分发。
3、应用场景与案例
(1)多级审批系统
- 场景:采购审批流程(部门经理→财务总监→CEO)
- 优势:灵活应对审批规则变化,如新增“董事会审批”节点
public class PurchaseRequest
{
public decimal Amount { get; set; }
}
public abstract class Approver
{
protected Approver NextApprover;
public void SetNextApprover(Approver next) => NextApprover = next;
public abstract void ProcessRequest(PurchaseRequest request);
}
public class Manager : Approver
{
public override void ProcessRequest(PurchaseRequest request)
{
if (request.Amount <= 10000)
{
Console.WriteLine("部门经理审批通过");
}
else
{
NextApprover?.ProcessRequest(request);
}
}
}
public class CFO : Approver
{
public override void ProcessRequest(PurchaseRequest request)
{
if (request.Amount <= 50000)
{
Console.WriteLine("财务总监审批通过");
}
else
{
NextApprover?.ProcessRequest(request);
}
}
}
(2)敏感词过滤系统
- 场景:依次检查涉黄、广告、政治敏感词
- 扩展性:可动态添加新的过滤规则
public class ContentFilter
{
public string Text { get; set; }
}
public abstract class FilterHandler
{
protected FilterHandler NextFilter;
public void SetNextFilter(FilterHandler next) => NextFilter = next;
public abstract bool Filter(ContentFilter content);
}
public class SexyWordFilter : FilterHandler
{
public override bool Filter(ContentFilter content)
{
if (content.Text.Contains("敏感词1"))
{
Console.WriteLine("存在涉黄内容");
return false;
}
return NextFilter?.Filter(content) ?? true;
}
}
public class AdsFilter : FilterHandler
{
public override bool Filter(ContentFilter content)
{
if (content.Text.Contains("广告链接"))
{
Console.WriteLine("存在广告内容");
return false;
}
return NextFilter?.Filter(content) ?? true;
}
}
4、扩展与优化
(1)动态构建链
- 通过配置文件或依赖注入动态组装链
- 优势:无需修改代码即可调整处理顺序
var chain = Configuration.GetSection("Handlers").Get<List<string>>();
Handler root = null;
Handler current = null;
foreach (var handlerName in chain)
{
var handler = Activator.CreateInstance(Type.GetType(handlerName)) as Handler;
if (root == null) root = handler;
else current.SetSuccessor(handler);
current = handler;
}
(2)中断链传递
- 若某个处理者完成请求,可终止传递
- 应用场景:快速失败(Fast-Fail)机制
public override void HandleRequest(int request)
{
if (CanHandle(request))
{
// 处理逻辑
return; // 中断传递
}
successor?.HandleRequest(request);
}
(3)责任链与中间件
- ASP.NET Core中间件管道是责任链模式的典型应用
- 对比:中间件模式强调“请求-响应”双向处理
public class LoggingMiddleware
{
private readonly RequestDelegate _next;
public LoggingMiddleware(RequestDelegate next) => _next = next;
public async Task InvokeAsync(HttpContext context)
{
Console.WriteLine("请求开始");
await _next(context);
Console.WriteLine("请求结束");
}
}
4、优缺点分析
(1)优点
- 解耦请求与处理:发送者无需关注处理细节。
- 动态配置链结构:支持运行时增减节点。
- 增强代码复用性:每个处理者独立封装逻辑。
(2)缺点
- 链过长导致性能问题:请求可能遍历整个链。
- 请求可能未被处理:需设计兜底逻辑。
- 调试困难:逻辑分散在多个处理者中。
模板方法模式👍
1、定义与核心思想
(1)定义
- 模板方法模式(Template Method Pattern)是一种行为型设计模式,其核心思想是定义一个操作中的算法骨架,将某些步骤的具体实现延迟到子类中,使得子类在不改变算法结构的前提下,可以重写算法的某些特定步骤。
- 该模式通过继承实现代码复用,适用于算法步骤稳定但部分细节可变的场景。
(2)核心原则
- 算法框架稳定:父类定义算法的整体流程(如流程步骤的调用顺序)。
- 可变细节延迟到子类:子类负责实现特定步骤的细节。
(3)模式与角色
- 抽象类(Abstract Class):定义算法的骨架和基本操作(包含具体方法、抽象方法和模板方法)。
- 具体子类(Concrete Class):实现父类中定义的抽象方法,提供特定步骤的实现。
(4)应用场景
- 流程审批系统:如请假流程(提交申请→领导审批→HR通知),不同公司的审批步骤可自定义。
- 日志记录器:记录日志的通用流程(打开连接→写入日志→关闭连接),支持多种存储方式(文件、数据库、邮件)。
- 数据解析工具:如处理不同格式文件(PDF、DOC、CSV),固定解析步骤(读取→清洗→转换),具体实现由子类完成。
2、C#代码实现
(1)定义抽象类
// 抽象试卷模板类
public abstract class ExamPaperTemplate
{
// 模板方法:定义答题流程
public void AnswerQuestions()
{
Question1();
Console.WriteLine($"答案:{Answer1()}");
Question2();
Console.WriteLine($"答案:{Answer2()}");
}
// 固定步骤(具体方法)
private void Question1()
{
Console.WriteLine("问题1:1+1=?");
}
private void Question2()
{
Console.WriteLine("问题2:2+2=?");
}
// 抽象步骤(由子类实现)
public abstract string Answer1();
public abstract string Answer2();
}
(2)实现具体子类
// 学生A的答卷
public class StudentAPaper : ExamPaperTemplate
{
public override string Answer1() => "2";
public override string Answer2() => "4";
}
// 学生B的答卷
public class StudentBPaper : ExamPaperTemplate
{
public override string Answer1() => "3"; // 错误答案示例
public override string Answer2() => "4";
}
(3)客户端调用
class Program
{
static void Main()
{
ExamPaperTemplate studentA = new StudentAPaper();
studentA.AnswerQuestions();
ExamPaperTemplate studentB = new StudentBPaper();
studentB.AnswerQuestions();
}
}
- 输出结果:
问题1:1+1=?
答案:2
问题2:2+2=?
答案:4
问题1:1+1=?
答案:3
问题2:2+2=?
答案:4
(4)关键代码解析
- 模板方法:
AnswerQuestions()方法定义了答题流程的固定步骤(问题展示和答案输出)。 - 抽象方法:
Answer1()和Answer2()由子类实现,提供可变逻辑。 - 具体方法:
Question1()和Question2()是父类中已实现的固定步骤。
(5)实际案例扩展
- 案例:多平台支付流程
public abstract class PaymentProcessor
{
public void ProcessPayment()
{
ValidateRequest();
ExecutePayment();
SendNotification();
}
protected abstract void ExecutePayment();
private void ValidateRequest() => Console.WriteLine("验证支付请求...");
private void SendNotification() => Console.WriteLine("发送支付成功通知...");
}
public class AliPayProcessor : PaymentProcessor
{
protected override void ExecutePayment() => Console.WriteLine("调用支付宝API完成支付");
}
public class WeChatPayProcessor : PaymentProcessor
{
protected override void ExecutePayment() => Console.WriteLine("调用微信支付API完成支付");
}
3、高级技巧
(1)钩子方法
- 钩子方法是模板方法模式中的可选步骤,子类可选择性覆盖以微调算法流程。例如:
public abstract class ReportGenerator
{
public void GenerateReport()
{
FetchData();
if (NeedFormatting()) FormatData();
SaveToFile();
}
protected virtual bool NeedFormatting() => true; // 钩子方法
protected abstract void FetchData();
protected virtual void FormatData() => Console.WriteLine("默认数据格式化");
protected abstract void SaveToFile();
}
(2)与策略模式结合
- 当需要动态切换算法步骤时,可结合策略模式,通过依赖注入实现步骤的灵活替换。
3、优缺点分析
(1)优点
- 代码复用性高:公共代码集中在父类,减少重复。
- 扩展性强:新增子类不影响现有代码,符合开闭原则。
- 流程控制统一:算法骨架由父类定义,避免子类随意修改流程。
(2)缺点
- 类膨胀问题:每个子类需单独实现抽象方法,可能导致类数量过多。
- 继承限制:C#不支持多重继承,若子类需复用其他类功能时受限。
(3)对比其他模式
| 模式 | 核心区别 |
|---|---|
| 工厂方法模式 | 关注对象创建,而模板方法关注算法流程。 |
| 策略模式 | 通过组合实现算法替换,模板方法通过继承实现步骤扩展。 |
迭代器模式👍
1、定义与核心思想
(1)定义
- 迭代器模式(Iterator Pattern)是一种行为型设计模式,其核心目标是为聚合对象(如集合、列表等)提供一种统一的遍历方式,而无需暴露其内部结构。
- 通过将遍历逻辑抽象为独立的迭代器对象,实现了数据访问与存储的解耦。
(2)结构与角色
- 抽象迭代器(Iterator):定义遍历元素的接口(如
MoveNext()、Current)。 - 具体迭代器(ConcreteIterator):实现抽象迭代器的逻辑,管理遍历状态(如光标位置)。
- 抽象聚合(Aggregate):定义创建迭代器的接口(如
GetEnumerator())。 - 具体聚合(ConcreteAggregate):实现聚合对象的具体数据结构(如数组、链表)。
(3)应用场景
- 集合遍历
- 统一遍历接口:无论集合内部是数组、链表还是树,客户端均可通过
foreach统一处理。 - 延迟执行(Lazy Evaluation):如LINQ查询通过迭代器延迟执行,仅在遍历时计算结果。
- 统一遍历接口:无论集合内部是数组、链表还是树,客户端均可通过
- 复合数据结构遍历
- 嵌套结构:例如遍历树形结构时,可通过迭代器实现深度优先或广度优先搜索。
- 数据流处理
- 分页加载:从数据库或网络流中分批读取数据,避免一次性加载内存溢出。
2、C#代码实现
(1)基于标准接口的实现
- C#通过
IEnumerable和IEnumerator接口原生支持迭代器模式:IEnumerable:定义获取迭代器的方法GetEnumerator()。IEnumerator:定义遍历逻辑,包含MoveNext()、Current和Reset()方法。
- 此方式需要手动管理状态,适用于需要高度定制化遍历逻辑的场景
public class CustomList : IEnumerable, IEnumerator {
private int[] _items = { 1, 2, 3 };
private int _position = -1;
public IEnumerator GetEnumerator() {
Reset();
return this;
}
public bool MoveNext() => ++_position < _items.Length;
public object Current => _items[_position];
public void Reset() => _position = -1;
}
(2)使用yield关键字简化实现
- C#通过
yield return自动生成状态机,隐藏了迭代器的复杂性 - 编译器会生成一个嵌套类,管理
Current、MoveNext()和状态机,适用于快速实现迭代逻辑。
public IEnumerable<char> GetAlphabet() {
for (char c = 'A'; c <= 'Z'; c++) {
yield return c; // 自动保存当前状态并返回元素
}
}
- 这种方式在内存效率和代码简洁性上优于手动实现
public IEnumerator GetEnumerator() {
for (int i = 0; i < 26; i++) {
yield return (char)('A' + i); // 动态生成字符序列
}
}
(3)泛型迭代器
- 通过
IEnumerable<T>和IEnumerator<T>支持类型安全遍历 - 泛型迭代器避免了装箱/拆箱开销,提高了性能
public class GenericList<T> : IEnumerable<T> {
private T[] _items;
public IEnumerator<T> GetEnumerator() {
foreach (T item in _items) {
yield return item;
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
3、扩展与进阶
(1)与设计模式的结合
- 组合模式:迭代器可用于遍历树形结构的组合对象。
- 工厂方法模式:聚合类通过工厂方法创建特定类型的迭代器。
(2)异步迭代器
- C# 8.0+支持
await foreach异步遍历 - 适用于IO密集型操作(如网络请求)
public async IAsyncEnumerable<int> FetchDataAsync() {
while (hasMoreData) {
var data = await FetchNextPageAsync();
foreach (var item in data) {
yield return item;
}
}
}
(3)自定义迭代策略
- 通过扩展方法增强迭代功能
- 此方法可实现链式查询,类似LINQ
public static IEnumerable<T> Filter<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
foreach (T item in source) {
if (predicate(item)) yield return item;
}
}
3、优缺点分析
(1)优点
- 解耦遍历与存储:聚合类只需关注数据存储,遍历逻辑由迭代器独立管理。
- 支持多种遍历方式:同一集合可提供正向、反向或过滤后的迭代器。
- 开闭原则:新增迭代器无需修改聚合类代码。
(2)缺点
- 性能开销:
yield生成的状态机可能带来轻微性能损耗,高频场景需谨慎。 - 复杂性增加:手动实现迭代器需维护状态,代码量较大。
中介者模式
1、定义与核心思想
(1)定义
- 中介者模式(Mediator Pattern)是一种行为型设计模式,通过引入中介者对象来封装多个对象间的交互,从而将原本复杂的网状通信结构转换为星型结构,降低对象间的直接耦合。
(2)结构与角色
- 抽象中介者(Mediator):定义通信接口,协调各对象交互。
- 具体中介者(ConcreteMediator):实现接口,持有所有同事对象引用,处理具体逻辑。
- 抽象同事类(Colleague):定义与中介者通信的接口。
- 具体同事类(ConcreteColleague):与其他同事通过中介者通信,而非直接引用。
(3)应用场景
- UI控件交互:如表单字段联动(如登录界面中单选按钮、输入框的联动)。
- 分布式系统协调:如订单系统中库存、支付、物流模块的协同。
- 游戏开发:管理玩家、NPC、场景间的通信。
2、C#代码实现
(1)典型实现
- 中介者(
ChatRoom)负责注册用户并转发消息。 - 同事类(
ChatUser)仅依赖中介者,无需直接引用其他用户
// 1. 定义中介者接口
public interface IChatMediator
{
void RegisterUser(User user);
void SendMessage(string message, User sender);
}
// 2. 具体中介者:管理用户及消息分发
public class ChatRoom : IChatMediator
{
private List<User> _users = new List<User>();
public void RegisterUser(User user)
{
_users.Add(user);
user.Mediator = this;
}
public void SendMessage(string message, User sender)
{
foreach (var user in _users.Where(u => u != sender))
{
user.Receive(message);
}
}
}
// 3. 抽象同事类
public abstract class User
{
public string Name { get; }
public IChatMediator Mediator { get; set; }
protected User(string name) => Name = name;
public abstract void Send(string message);
public abstract void Receive(string message);
}
// 4. 具体同事类
public class ChatUser : User
{
public ChatUser(string name) : base(name) { }
public override void Send(string message)
{
Console.WriteLine($"{Name}发送消息:{message}");
Mediator.SendMessage(message, this);
}
public override void Receive(string message)
{
Console.WriteLine($"{Name}收到消息:{message}");
}
}
// 客户端调用
var mediator = new ChatRoom();
var user1 = new ChatUser("Alice");
var user2 = new ChatUser("Bob");
mediator.RegisterUser(user1);
mediator.RegisterUser(user2);
user1.Send("Hello, Bob!");
(2)扩展实现:事件驱动中介者
- 结合C#的事件机制,实现松耦合交互
- 优势:进一步解耦中介者与同事类,适用于异步通信场景
// 定义事件参数
public class MessageEventArgs : EventArgs
{
public string Message { get; }
public User Sender { get; }
public MessageEventArgs(string message, User sender)
=> (Message, Sender) = (message, sender);
}
// 中介者通过事件通知
public class EventMediator
{
public event EventHandler<MessageEventArgs> MessageReceived;
public void Broadcast(string message, User sender)
=> MessageReceived?.Invoke(this, new MessageEventArgs(message, sender));
}
// 同事类订阅事件
public class EventUser
{
public EventMediator Mediator { get; }
public EventUser(EventMediator mediator)
{
Mediator = mediator;
Mediator.MessageReceived += OnMessageReceived;
}
private void OnMessageReceived(object sender, MessageEventArgs e)
{
if (e.Sender != this)
Console.WriteLine($"收到消息:{e.Message}");
}
public void Send(string message)
=> Mediator.Broadcast(message, this);
}
(3)实战案例:电商订单系统
- 需求:订单创建需协调库存锁定、支付处理、物流调度。
- 优势:交互逻辑集中管理,新增模块时只需修改中介者
public interface IOrderMediator
{
void LockStock();
void ProcessPayment();
void ScheduleDelivery();
void Rollback();
}
public class OrderSystem : IOrderMediator
{
private InventoryService _inventory;
private PaymentService _payment;
private LogisticsService _logistics;
public void CreateOrder()
{
try
{
LockStock();
ProcessPayment();
ScheduleDelivery();
}
catch
{
Rollback();
}
}
public void LockStock() => _inventory.Lock();
public void ProcessPayment() => _payment.Charge();
public void ScheduleDelivery() => _logistics.Schedule();
public void Rollback()
{
_inventory.Release();
_payment.Refund();
}
}
(4)最佳实践
- 适用条件:对象间存在复杂网状依赖,且交互频繁变化的场景。
- 设计原则:
- 单一职责:中介者仅处理交互逻辑,同事类专注自身行为。
- 开闭原则:通过扩展中介者而非修改现有代码实现新功能。
- 性能优化:对于高频交互场景,可结合异步消息队列或缓存机制。
3、优缺点分析
(1)优点
- 降低耦合:对象间依赖关系从多对多变为一对多,符合迪米特法则。
- 集中控制:交互逻辑统一管理,便于维护和扩展。
- 职责清晰:同事类仅关注自身业务,交互职责转移至中介者。
(2)缺点
- 中介者复杂度高:若交互逻辑复杂,中介者可能成为“上帝对象”。
- 性能损耗:集中转发可能导致额外开销。
(3)对比其他模式
| 模式 | 核心差异 |
|---|---|
| 观察者模式 | 处理一对多依赖,观察者被动接收通知;中介者模式处理多对多交互。 |
| 门面模式 | 封装子系统对外接口(单向);中介者协调内部对象(双向)。 |
| 代理模式 | 控制单个对象访问;中介者管理多个对象交互。 |
更多推荐


所有评论(0)