• 责任链模式(Chain of Responsibility)


    模式定义

    责任链模式(Chain of Responsibility): 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条对象连成一条链,并沿着这条链传递请求。

    UML类图

    • 抽象处理者(Handler) :定义一个处理请求的接口。关联自身类型的变量。
    • 具体处理者(Concrete Handler): 实现 抽象处理者中的处理方法,处理请求或者传递给下个处理对象。
    • 客户端(Client):设置处理链,并调用。

    代码结构

    class ChainClient
    	{
    		 public void Run()
    		{
    			Handler h1 = new ConcreteHandler1();
    			Handler h2 = new ConcreteHandler2();
    			Handler h3 = new ConcreteHandler3();
    			h1.SetSuccessor(h2);
    			h2.SetSuccessor(h3);
    
    			int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };
    
    			foreach (int request in requests)
    			{
    				h1.HandleRequest(request);
    			}
    			Console.ReadKey();
    		}
    	}
    
    	abstract class Handler
    	{
    		protected Handler successor;
    
    		public void SetSuccessor(Handler successor)
    		{
    			this.successor = successor;
    		}
    
    		public abstract void HandleRequest(int request);
    	}
    
    	class ConcreteHandler1 : Handler
    	{
    		public override void HandleRequest(int request)
    		{
    			if (request >= 0 && request < 10)
    			{
    				Console.WriteLine("{0} handled request {1}",this.GetType().Name, request);
    			}
    			else if (successor != null)
    			{
    				successor.HandleRequest(request);
    			}
    		}
    	}
    
    	class ConcreteHandler2 : Handler
    	{
    		public override void HandleRequest(int request)
    		{
    			if (request >= 10 && request < 20)
    			{
    				Console.WriteLine("{0} handled request {1}",this.GetType().Name, request);
    			}
    			else if (successor != null)
    			{
    				successor.HandleRequest(request);
    			}
    		}
    	}
    
    	class ConcreteHandler3 : Handler
    	{
    		public override void HandleRequest(int request)
    		{
    			if (request >= 20 && request < 30)
    			{
    				Console.WriteLine("{0} handled request {1}",this.GetType().Name, request);
    			}
    			else if (successor != null)
    			{
    				successor.HandleRequest(request);
    			}
    		}
    	}
    

    情景案例

    这里以大学中请假为例:少于2天班长处理,多于2天班长交给指导员处理,多于5天指导员交给系主任处理,多于30天不准。

    class RealWorldChainClient
    	{
    		public void Run()
    		{
    			Approver h1 = new Monitor();
    			Approver h2 = new Instructor();
    			Approver h3 = new DepartmentHead();
    			h1.SetSuccessor(h2);
    			h2.SetSuccessor(h3);
    
    			int[] requests = { 2, 5, 14, 35 };
    
    			foreach (int request in requests)
    			{
    				h1.HandleRequest(request);
    			}
    			Console.ReadKey();
    		}
    	}
    
    	abstract class Approver
    	{
    		protected Approver successor;
    
    		public void SetSuccessor(Approver successor)
    		{
    			this.successor = successor;
    		}
    
    		public abstract void HandleRequest(int days);
    	}
    
    	/// <summary>
    	/// 班长
    	/// </summary>
    	class Monitor : Approver
    	{
    		public override void HandleRequest(int days)
    		{
    			if (days >= 0 && days <= 2)
    			{
    				Console.WriteLine("我是班长,批准请假{0}天",days);
    			}
    			else if (successor != null)
    			{
    				successor.HandleRequest(days);
    			}
    		}
    	}
    
    	/// <summary>
    	/// 指导员
    	/// </summary>
    	class Instructor : Approver
    	{
    		public override void HandleRequest(int days)
    		{
    			if (days >= 0 && days < 10)
    			{
    				Console.WriteLine("我是指导员,批准请假{0}天", days);
    			}
    			else if (successor != null)
    			{
    				successor.HandleRequest(days);
    			}
    		}
    	}
    
    	/// <summary>
    	/// 系主任
    	/// </summary>
    	class DepartmentHead : Approver
    	{
    		public override void HandleRequest(int days)
    		{
    			if (days >= 0 && days < 30)
    			{
    				Console.WriteLine("我是指导员,批准请假{0}天", days);
    			}
    			else
    			{
    				Console.WriteLine("请假天数太多了,退学吧!");
    			}
    		}
    	}
    

    自问自答

    小a:你的博客好冷清呀!!!我感觉你上面讲的例子还不如用if()....else....简单明了,整那么多类倒是增加了复杂性,感觉这个模式没必要?

    LoveTomato: 啊!!!确实博客比较冷清,万事开头难吗?但开头难也要开头的吗。
    回答正题 确实业务比较简单,顺序编程简单快捷。但是项目中往往是比较复杂的,比如好多网站需要用户填入的表单,后台验证数据的有效性。假设验证的指标有

    1. 必填性验证
    2. 数据类型验证(时间类型的值是否有效等)
    3. 业务验证(需要查询数据库)

    这样每个验证都需要大段的代码,在if...else中维护的心情你懂的,而且每次添加项新的验证都需要修改if...else

  • 相关阅读:
    SGU 495 Kids and Prizes 概率DP 或 数学推理
    poj 2799 IP Networks 模拟 位运算
    uva 202 Repeating Decimals 模拟
    poj 3158 Kickdown 字符串匹配?
    uva 1595 Symmetry 暴力
    uva 201 Squares 暴力
    uva 1594 Ducci Sequence 哈希
    uva 1368 DNA Consensus String 字符串
    数字、字符串、列表的常用操作
    if条件判断 流程控制
  • 原文地址:https://www.cnblogs.com/LoveTomato/p/8406461.html
Copyright © 2020-2023  润新知