意图
使多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
结构
职责链结构图
适用性
- 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定;
- 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
- 需要动态地指定可以处理请求的对象集。
优缺点
- 该模式使一个对象无需知道其他哪一个对象处理请求,从而降低耦合;
- 允许运行时刻对该链接进行动态地增/减,增强了对象指派职责的灵活性;
- 由于没有明确的接受者,因此不保证请求会被处理;
示例
模拟一个图形用户界面的上下文帮助机制,用户在界面的任意部分上点击就可以得到帮助信息。
实现(C#)
职责链示例结构图
using System;
public enum Topic
{
NO_HELP_TOPIC,
HELP_TOPIC
}
public abstract class HelpHandler
{
private HelpHandler successor;
private Topic topic;
protected HelpHandler(HelpHandler successor, Topic topic)
{
this.successor = successor;
this.topic = topic;
}
private bool HasHelp()
{
return this.topic != Topic.NO_HELP_TOPIC;
}
// 模板方法
public void HandleHelp()
{
if(HasHelp())
{
DoHandleHelp();
}
else if(this.successor != null)
{
this.successor.DoHandleHelp();
}
}
protected abstract void DoHandleHelp();
}
public class Application : HelpHandler
{
public Application(HelpHandler successor, Topic topic) : base(successor,topic){}
protected override void DoHandleHelp()
{
Console.WriteLine("「应用程序」提供的帮助信息.");
}
}
public class Widget : HelpHandler
{
public Widget(HelpHandler successor, Topic topic) : base(successor, topic) {}
protected override void DoHandleHelp()
{
Console.WriteLine("「窗口小部件」提供的帮助信息.");
}
}
public class Dialog : Widget
{
public Dialog(HelpHandler successor, Topic topic) : base(successor, topic){}
protected override void DoHandleHelp()
{
Console.WriteLine("「对话框」提供的帮助信息.");
}
}
public class Button : Widget
{
public Button(HelpHandler successor, Topic topic) : base(successor,topic){}
protected override void DoHandleHelp()
{
Console.WriteLine("「按钮控件」提供的帮助信息.");
}
}
public class App
{
public static void Main(string[] args)
{
Application application = new Application(null,Topic.HELP_TOPIC); // 提供帮助
Dialog dialog = new Dialog(application, Topic.HELP_TOPIC); // 提供帮助
Button button = new Button(dialog, Topic.NO_HELP_TOPIC); // 不提供帮助
// 显示帮助信息
button.HandleHelp();
}
}
// 控制台输出:
// 「对话框」提供的帮助信息.