Iron之职责链
需求:
"Iron"的建造一直没有停止,现在单个部件是有的,但是在部件从工厂里出来的时候,在组装到一起之前,我们还是非常有必要对部件进行质量检测,或者是其它个方面的检测,又或者是设置部件标识信息等等,这些操作可以是有序的(也可以是无序的)。
现在为了实现上面的所讲的功能来进行演示,然过程中会发现问题,然后解决问题。这里不多说了直接进入主题。
问题的发现:
首先我定义了一个ComponentModel类,它是要被检验的对象
1 /// <summary> 2 /// 部件 3 /// </summary> 4 public class ComponentModel 5 { 6 public string Name { get; set; } 7 public int Value 8 { 9 get 10 { 11 return 5; 12 } 13 } 14 }
这里先定义了一个请求处理类型的枚举,下面要用到,这样比用什么字符串或者是数字来作条件判断要好很多。
1 /// <summary> 2 /// 请求的处理类型 3 /// </summary> 4 public enum RequestState 5 { 6 /// <summary> 7 /// 检测 8 /// </summary> 9 Check, 10 /// <summary> 11 /// 设置基础值 12 /// </summary> 13 SetDefValue 14 15 }
再然后,我们再来定义检验ComponentModel类的类型:
1 /// <summary> 2 /// 处理请求类1 3 /// </summary> 4 public class ConcreteHandlerCaseOne 5 { 6 private ComponentModel _comModel; 7 public ConcreteHandlerCaseOne(ComponentModel comModel) 8 { 9 _comModel = comModel; 10 } 11 public void HandleRequest(RequestState reqState) 12 { 13 switch (reqState) 14 { 15 case RequestState.Check: 16 if (_comModel.Value > 5) 17 { 18 //执行处理 19 } 20 break; 21 case RequestState.SetDefValue: 22 _comModel.Name = "默认部件"; 23 //执行处理 24 break; 25 default: 26 27 break; 28 } 30 } 31 } 32 /// <summary> 33 /// 处理请求类2 34 /// </summary> 35 public class ConcreteHandlerCaseTwo 36 { 37 private ComponentModel _comModel; 38 public ConcreteHandlerCaseTwo(ComponentModel comModel) 39 { 40 _comModel = comModel; 41 } 42 public void HandleRequest(RequestState reqState) 43 { 44 switch (reqState) 45 { 46 case RequestState.Check: 47 if (_comModel.Value > 5) 48 { 49 //执行处理 50 } 51 break; 52 case RequestState.SetDefValue: 53 _comModel.Name = "默认部件"; 54 //执行处理 55 break; 56 default: 57 58 break; 59 60 } 61 } 62 }
定义了两个类型,ConcreteHandlerCaseOne和ConcreteHandlerCaseTwo两个类型,都是用来处理检测ComponentModel类型的,现在这些类型都齐全了我们来检测一下吧。
1 ComponentModel comModel = new ComponentModel(); 2 ConcreteHandlerCaseOne caseone = new ConcreteHandlerCaseOn(comModel); 3 caseone.HandleRequest(RequestState.Check); 4 ConcreteHandlerCaseTwo casetwo = new ConcreteHandlerCaseTw(comModel); 5 casetwo.HandleRequest(RequestState.Check);
对的,就是这样,一次次的检测下去,如果要检测20次,并且都是不同的实现,那将非常可怕,代码冗余,而且请求调用方和处理方的耦合度也很大,那要怎么样让代码更精简,并且还能有效的解耦,这里就要用到职责链模式。
为了避免请求的发送者和接收者之间的耦合关系,使多个接受对象都有机会处理请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
――Gof
这里要强调一下的是本篇的示例中并没有完全遵从设计模式的定义,还是按照本文开始的功能需求来做的设计,当然了模式的核心不变。
设计模式的思想:
现在先对处理方进行抽象:
1 /// <summary> 2 /// 抽象处理者 3 /// </summary> 4 public abstract class Handle 5 { 6 protected Handle Successor; 7 public void SetSuccessor(Handle successor) 8 { 9 this.Successor = successor; 10 } 11 public abstract void HandleRequest(RequestStatereqState,ComponentModel comModel); 12 13 }
既然有了抽象,那就得有具体的实现:
1 /// <summary> 2 /// 具体处理者 3 /// </summary> 4 public class ConcreteHandlerA : Handle 5 { 6 public override void HandleRequest(RequestState reqState, ComponentModel comModel) 7 { 8 switch (reqState) 9 { 10 case RequestState.Check: 11 //执行处理 12 13 break; 14 case RequestState.SetDefValue: 15 //执行处理 16 break; 17 default: 18 this.Successor.HandleRequest(reqState, comModel); 19 break; 20 21 } 22 } 23 } 24 /// <summary> 25 /// 具体处理者 26 /// </summary> 27 public class ConcreteHandlerB : Handle 28 { 29 public override void HandleRequest(RequestState reqState, ComponentModel comModel) 30 { 31 switch (reqState) 32 { 33 case RequestState.Check: 34 //执行处理 35 break; 36 case RequestState.SetDefValue: 37 //执行处理 38 break; 39 default: 40 this.Successor.HandleRequest(reqState, comModel); 41 break; 42 43 } 44 } 45 }
这里的类型应该只定义一个的是为了让大家看的更明白。
在这里看抽象处理者Handle类型,它里面有个protected级别的变量Successor,Successor呢就代表着链表中每一环的指针,指向谁呢?当然是指向下一个处理者。
现在来看一下调用的代码:
1 ComponentModel comModel = new ComponentModel(); 2 Handle handlerA = new ConcreteHandlerA(); 3 Handle handlerB = new ConcreteHandlerB(); 4 handlerA.SetSuccessor(handlerB); 5 handlerA.HandleRequest(RequestState.Check, comModel);
看上去已经不错了,耦合度还是很大的,对于handlerA的调用,还是再调用方直接调用的,这时需要一个中间层,
看一下中间层的定义:
1 /// <summary> 2 /// ChainOfResponsibility模式帮助类 3 /// </summary> 4 public class CORUnit 5 { 6 private Handle _Handle; 7 8 private ComponentModel _ComModel; 9 10 public CORUnit(ComponentModel commodel) 11 : this(null, commodel) 12 { 13 _ComModel = commodel; 14 } 15 public CORUnit(Handle Handle, ComponentModel commodel) 16 { 17 _Handle = Handle; 18 _ComModel = commodel; 19 } 20 public void RegisterHandle(Handle handle) 21 { 22 if (_Handle != null) 23 { 24 _Handle.SetSuccessor(handle);//指向 处理链中的下一个 处理模块 25 } 26 else 27 { 28 _Handle = handle; 29 } 30 } 31 public void HandleRequest(RequestState reqState) 32 { 33 _Handle.HandleRequest(reqState, _ComModel); 34 } 35 }
通过加了一层,再来看一下调用方的代码:
1 ComponentModel comModel = new ComponentModel(); 2 CORUnit corunit = new CORUnit(comModel); 3 corunit.RegisterHandle(new ConcreteHandlerA()); 4 corunit.RegisterHandle(new ConcreteHandlerB()); 5 corunit.HandleRequest(RequestState.Check); 6 //执行处理 7 //comModel的一些处理
是不是感觉调用方,跟实际的处理方之间的关系变得很弱了,这样目的也就达到了。