(13)行为型模式——责任链

行为型模式——责任链(Chain of Responsibility)

问题背景

当希望让多个对象都有处理请求的机会时,考虑使用责任链。责任链的应用场景比较有限,这里就直接照搬书中的案例了。考虑一个图形用户界面中的上下文有关的帮助机制:用户在不同的界面点击帮助按钮,会显示不同的帮助文档。如果界面有特定的帮助文档,则显示特定的帮助文档;如果界面没有特定的帮助文档,则显示上层界面的帮助文档;如果上层界面也没有,则继续向上……这种递归传递请求,直到有人处理的逻辑,就是责任链。

解决方案

对于所有控件,都应该有一个HandleHelp方法用来处理帮助请求,这个方法的逻辑是:检查自己是否能够处理请求,如果能,则直接处理;如果不能,则将请求转发给下一个对象(父控件)。所以,每个控件还应该维护一个对其父控件的引用。使用责任链的程序结构是这样的:
程序结构
这样,在用户发出请求时,系统就会自动递归地传递请求,直到有人处理。

效果

  1. 使多个对象都有机会处理同一个请求。
  2. 使用户和具体对象解耦。

缺陷

责任链无法保证用户的请求一定被处理,因为请求可能传递到最后都没人能处理。

相关模式

  1. 复合:可以把复合结构的一条从叶子到根的路径作为一条责任链。

实现

using System;

namespace CoR
{
    class Client
    {
        public interface IControl
        {
            void HandleHelp();
        }

        public abstract class Control : IControl
        {
            protected IControl parent;
            public Control(IControl parent)
            {
                this.parent = parent;
            }
            public abstract void HandleHelp();
        }

        public class ControlA : Control
        {
            public ControlA(IControl parent) : base(parent) { }
            public override void HandleHelp()
            {
                if (parent == null)
                {
                    Console.WriteLine("无法处理该请求");
                    return;
                }
                Console.WriteLine("ControlA不能处理请求,将向下传递该请求");
                parent.HandleHelp();
            }
        }

        public class ControlB : Control
        {
            public ControlB(IControl parent) : base(parent) { }
            public override void HandleHelp()
            {
                if (parent == null)
                {
                    Console.WriteLine("无法处理该请求");
                    return;
                }
                Console.WriteLine("ControlB不能处理请求,将向下传递该请求");
                parent.HandleHelp();
            }
        }

        public class ControlC : Control
        {
            public ControlC(IControl parent) : base(parent) { }
            public override void HandleHelp()
            {
                if (parent == null)
                {
                    Console.WriteLine("无法处理该请求");
                    return;
                }
                Console.WriteLine("ControlC不能处理请求,将向下传递该请求");
                parent.HandleHelp();
            }
        }

        public class ControlD : Control
        {
            public ControlD(IControl parent) : base(parent) { }
            public override void HandleHelp()
            {
                Console.WriteLine("ControlD能处理请求,将处理该请求");
                Console.WriteLine("处理完成");
            }
        }

        static void Main(string[] args)
        {
            Console.WriteLine("模拟无法处理的情景:");
            var c3 = new ControlA(null);
            var c2 = new ControlB(c3);
            var c1 = new ControlC(c2);
            c1.HandleHelp();

            Console.WriteLine();

            Console.WriteLine("模拟能够处理的场景:");
            var C5 = new ControlD(null);
            var C4 = new ControlB(C5);
            var C3 = new ControlC(C4);
            var C2 = new ControlA(C3);
            var C1 = new ControlB(C2);
            C1.HandleHelp();
        }
    }
}

运行结果

发布了27 篇原创文章 · 获赞 41 · 访问量 2077

猜你喜欢

转载自blog.csdn.net/DIAX_/article/details/104206127