C#设计模式之职责链
Iron之职责链
需求:
"Iron"的建造一直没有停止,现在单个部件是有的,但是在部件从工厂里出来的时候,在组装到一起之前,我们还是非常有必要对部件进行质量检测,或者是其它个方面的检测,又或者是设置部件标识信息等等,这些操作可以是有序的(也可以是无序的)。
现在为了实现上面的所讲的功能来进行演示,然过程中会发现问题,然后解决问题。这里不多说了直接进入主题。
问题的发现:
首先我定义了一个ComponentModel类,它是要被检验的对象
1///<summary>2///部件3///</summary>4publicclassComponentModel5{6publicstringName{get;set;}7publicintValue8{9get10{11return5;12}13}14}
这里先定义了一个请求处理类型的枚举,下面要用到,这样比用什么字符串或者是数字来作条件判断要好很多。
1///<summary>2///请求的处理类型3///</summary>4publicenumRequestState5{6///<summary>7///检测8///</summary>9Check,10///<summary>11///设置基础值12///</summary>13SetDefValue1415}
再然后,我们再来定义检验ComponentModel类的类型:
1///<summary>2///处理请求类13///</summary>4publicclassConcreteHandlerCaseOne5{6privateComponentModel_comModel;7publicConcreteHandlerCaseOne(ComponentModelcomModel)8{9_comModel=comModel;10}11publicvoidHandleRequest(RequestStatereqState)12{13switch(reqState)14{15caseRequestState.Check:16if(_comModel.Value>5)17{18//执行处理19}20break;21caseRequestState.SetDefValue:22_comModel.Name="默认部件";23//执行处理24break;25default:2627break;28}30}31}32///<summary>33///处理请求类234///</summary>35publicclassConcreteHandlerCaseTwo36{37privateComponentModel_comModel;38publicConcreteHandlerCaseTwo(ComponentModelcomModel)39{40_comModel=comModel;41}42publicvoidHandleRequest(RequestStatereqState)43{44switch(reqState)45{46caseRequestState.Check:47if(_comModel.Value>5)48{49//执行处理50}51break;52caseRequestState.SetDefValue:53_comModel.Name="默认部件";54//执行处理55break;56default:5758break;5960}61}62}
定义了两个类型,ConcreteHandlerCaseOne和ConcreteHandlerCaseTwo两个类型,都是用来处理检测ComponentModel类型的,现在这些类型都齐全了我们来检测一下吧。
1ComponentModelcomModel=newComponentModel();2ConcreteHandlerCaseOnecaseone=newConcreteHandlerCaseOn(comModel);3caseone.HandleRequest(RequestState.Check);4ConcreteHandlerCaseTwocasetwo=newConcreteHandlerCaseTw(comModel);5casetwo.HandleRequest(RequestState.Check);
对的,就是这样,一次次的检测下去,如果要检测20次,并且都是不同的实现,那将非常可怕,代码冗余,而且请求调用方和处理方的耦合度也很大,那要怎么样让代码更精简,并且还能有效的解耦,这里就要用到职责链模式。
为了避免请求的发送者和接收者之间的耦合关系,使多个接受对象都有机会处理请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
——Gof
这里要强调一下的是本篇的示例中并没有完全遵从设计模式的定义,还是按照本文开始的功能需求来做的设计,当然了模式的核心不变。
设计模式的思想:
现在先对处理方进行抽象:
1///<summary>2///抽象处理者3///</summary>4publicabstractclassHandle5{6protectedHandleSuccessor;7publicvoidSetSuccessor(Handlesuccessor)8{9this.Successor=successor;10}11publicabstractvoidHandleRequest(RequestStatereqState,ComponentModelcomModel);1213}
既然有了抽象,那就得有具体的实现:
1///<summary>2///具体处理者3///</summary>4publicclassConcreteHandlerA:Handle5{6publicoverridevoidHandleRequest(RequestStatereqState,ComponentModelcomModel)7{8switch(reqState)9{10caseRequestState.Check:11//执行处理1213break;14caseRequestState.SetDefValue:15//执行处理16break;17default:18this.Successor.HandleRequest(reqState,comModel);19break;2021}22}23}24///<summary>25///具体处理者26///</summary>27publicclassConcreteHandlerB:Handle28{29publicoverridevoidHandleRequest(RequestStatereqState,ComponentModelcomModel)30{31switch(reqState)32{33caseRequestState.Check:34//执行处理35break;36caseRequestState.SetDefValue:37//执行处理38break;39default:40this.Successor.HandleRequest(reqState,comModel);41break;4243}44}45}
这里的类型应该只定义一个的是为了让大家看的更明白。
在这里看抽象处理者Handle类型,它里面有个protected级别的变量Successor,Successor呢就代表着链表中每一环的指针,指向谁呢?当然是指向下一个处理者。
现在来看一下调用的代码:
1ComponentModelcomModel=newComponentModel();2HandlehandlerA=newConcreteHandlerA();3HandlehandlerB=newConcreteHandlerB();4handlerA.SetSuccessor(handlerB);5handlerA.HandleRequest(RequestState.Check,comModel);
看上去已经不错了,耦合度还是很大的,对于handlerA的调用,还是再调用方直接调用的,这时需要一个中间层,
看一下中间层的定义:
1///<summary>2///ChainOfResponsibility模式帮助类3///</summary>4publicclassCORUnit5{6privateHandle_Handle;78privateComponentModel_ComModel;910publicCORUnit(ComponentModelcommodel)11:this(null,commodel)12{13_ComModel=commodel;14}15publicCORUnit(HandleHandle,ComponentModelcommodel)16{17_Handle=Handle;18_ComModel=commodel;19}20publicvoidRegisterHandle(Handlehandle)21{22if(_Handle!=null)23{24_Handle.SetSuccessor(handle);//指向处理链中的下一个处理模块25}26else27{28_Handle=handle;29}30}31publicvoidHandleRequest(RequestStatereqState)32{33_Handle.HandleRequest(reqState,_ComModel);34}35}
通过加了一层,再来看一下调用方的代码:
1ComponentModelcomModel=newComponentModel();2CORUnitcorunit=newCORUnit(comModel);3corunit.RegisterHandle(newConcreteHandlerA());4corunit.RegisterHandle(newConcreteHandlerB());5corunit.HandleRequest(RequestState.Check);6//执行处理7//comModel的一些处理
是不是感觉调用方,跟实际的处理方之间的关系变得很弱了,这样目的也就达到了。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。