zoukankan      html  css  js  c++  java
  • 责任链模式(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

  • 相关阅读:
    SPSS Clementine 数据挖掘入门1
    SPSS19.0实战之多元线性回归
    SPSS19.0实战之聚类分析
    使用PowerDesigner建立数据库模型【转】
    Power Desginer系列03【转载】
    Power Desginer系列02【转载】
    Power Desginer系列01【转摘】
    Power Desginer系列00【转载】
    PowerDesigner概念设计模型(CDM)中的3种实体关系
    PowerDesigner教程系列(一)概念数据模型
  • 原文地址:https://www.cnblogs.com/LoveTomato/p/8406461.html
Copyright © 2011-2022 走看看