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