模式简介
责任链模式是一种行为型设计模式,用于对请求的发起者与处理者进行解耦,同时也用于管理复杂的或繁多的处理流程,责任链也可以看作处理链或者流程链,当一个请求处理系统需要处理多种不同类型的请求或者对于某个请求需要按顺序分步处理时就可以采用责任链模式,并且责任链是易于管理和扩展的,可以对责任链上的处理节点进行增加和删除,也可以对多个责任链进行连接。
常见的应用场景:事件处理系统、审批流程、日志记录、Web请求中间件、异常处理、菜单或命令的处理、工作流程管理等。
模式结构
-
Handler(处理者):
- 定义一个处理请求的接口。
- 持有一个指向下一个处理者的引用(可选)。
- 可以实现一个默认的处理行为。
- 提供一个方法用于处理请求,通常命名为
HandleRequest
或类似。
-
ConcreteHandler(具体处理者):
- 实现处理请求的具体逻辑。
- 如果能够处理请求,则处理之;否则,将请求传递给下一个处理者。
-
Client(客户端):
- 创建处理者链并向链的起始对象发送请求。
- 与处理者的抽象接口交互,无需关心具体的处理者实现。
工作原理
-
请求的传递:
- 客户端创建一个处理者链,并将请求发送给链的起始处理者(通常是具体处理者的实例)。
- 每个处理者对象都有一个指向下一个处理者的引用。
- 请求从链的起始点开始沿着链传递,直到有一个处理者能够处理它或者到达链的末尾。
-
处理请求:
- 当一个处理者收到请求时,它首先检查自己是否能够处理请求。如果能够处理,就执行相应的处理逻辑。
- 如果处理者无法处理请求,它将请求传递给下一个处理者,即调用下一个处理者的处理方法。
-
终止条件:
- 处理者链的末尾通常是一个没有后继处理者的处理者,或者后继处理者被设置为
null
。 - 这样设计是为了确保链中的每个处理者都有机会处理请求。
- 处理者链的末尾通常是一个没有后继处理者的处理者,或者后继处理者被设置为
-
动态添加处理者:
- 责任链模式支持动态添加和移除处理者,因此客户端可以灵活地调整链的结构。
代码示例(C#)
提示:可在本栏目的资源篇“设计模式代码示例合集”下载所有完整代码资源。
快捷键:Shortcut.cs
namespace CORPattern;
// 快捷键
enum Shortcut
{
None, CTRL_X, CTRL_C, CTRL_V
}
快捷键指令处理者:ShortcutHandler.cs
namespace CORPattern;
// 快捷键处理基类
abstract class ShortcutHandler
{
protected ShortcutHandler nextHandler; // 下一个处理者
public ShortcutHandler(ShortcutHandler nextHandler)
{
this.nextHandler = nextHandler;
}
public abstract void Handle(Shortcut shortcut); // 抽象方法:快捷键指令处理
}
// 剪切处理
class Cut : ShortcutHandler
{
public Cut(ShortcutHandler nextHandler) : base(nextHandler) { }
public override void Handle(Shortcut shortcut)
{
if (shortcut == Shortcut.CTRL_X) Console.WriteLine("Cut:已剪切文本...");
else if (nextHandler != null) nextHandler.Handle(shortcut);
else Console.WriteLine("Cut:责任链无法处理当前所指定的快捷键指令...");
}
}
// 复制处理
class Copy : ShortcutHandler
{
public Copy(ShortcutHandler nextHandler) : base(nextHandler) { }
public override void Handle(Shortcut shortcut)
{
if (shortcut == Shortcut.CTRL_C) Console.WriteLine("Copy:已复制文本...");
else if (nextHandler != null) nextHandler.Handle(shortcut);
else Console.WriteLine("Copy:责任链无法处理当前所指定的快捷键指令...");
}
}
// 粘贴处理
class Paste : ShortcutHandler
{
public Paste(ShortcutHandler nextHandler) : base(nextHandler) { }
public override void Handle(Shortcut shortcut)
{
if (shortcut == Shortcut.CTRL_V) Console.WriteLine("Paste:已粘贴文本...");
else if (nextHandler != null) nextHandler.Handle(shortcut);
else Console.WriteLine("Paste:责任链无法处理当前所指定的快捷键指令...");
}
}
测试代码:Program.cs
// ************* 9.责任链模式测试 **************
using CORPattern;
# nullable disable
// 定义三种快捷键指令的处理,指令处理的传递顺序:cut => copy => paste
ShortcutHandler paste = new Paste(null);
ShortcutHandler copy = new Copy(paste);
ShortcutHandler cut = new Cut(copy);
// 开始测试Ctrl+V指令
cut.Handle(Shortcut.CTRL_V);
cut.Handle(Shortcut.CTRL_X);
cut.Handle(Shortcut.CTRL_C);
cut.Handle(Shortcut.None);
代码解说
上述代码简单模拟了对剪切、复制和粘贴快捷键指令的处理。三个快捷键指令分别对应三个处理者,并且每个处理者会在实例化时记录下一个处理者,当该处理者无法处理指令时传递给下一个处理者,将所有的处理者组合成一个处理链,这就是对责任链模式的简单应用。
如果这篇文章对你有帮助,请给作者点个赞吧!