职责链(chain of responsibility)

意图

使多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

结构

职责链(chain of responsibility)_第1张图片
职责链结构图

适用性

  • 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定;
  • 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
  • 需要动态地指定可以处理请求的对象集。

优缺点

  • 该模式使一个对象无需知道其他哪一个对象处理请求,从而降低耦合
  • 允许运行时刻对该链接进行动态地增/减,增强了对象指派职责的灵活性
  • 由于没有明确的接受者,因此不保证请求会被处理;


示例

模拟一个图形用户界面的上下文帮助机制,用户在界面的任意部分上点击就可以得到帮助信息。

实现(C#)

职责链(chain of responsibility)_第2张图片
职责链示例结构图
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();
    }
}

// 控制台输出:
//  「对话框」提供的帮助信息.

你可能感兴趣的:(职责链(chain of responsibility))