3.1.1 模式意图:
在系统中,同一个元素可能有多个对象根据优先级对其进行逐步处理,并通过返回处理的状态判断(Ture、False、Null等)是否交由下一对象操作,一般情况下我们会使用
if elseif else
语句进行跳转,但是如果处理对象较多,处理优先级变动频繁,再用else语句显然不是一个优雅的行为,这时我们可以使用责任链模式来完成上述需求。
3.1.2 模式概念:
它属于行为型模式,使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
3.1.3 模式元素:
- 请求元素(Responsibility)
- 处理链节点抽象(Handler)
- 处理链节点细节(ConcreteHandler1、ConcreteHandler2、ConcreteHandler3)
3.1.4 代码示例:
下面以一个吃食物请求的流程为背景,用责任链模式来展示代码示例
public class ResponsibilityContext
{
public string Type = "肉类";
public string Description = "我想吃**肉";
public bool AuditResult = false;
public string AuditRemark = "";
}
public abstract class Handler
{
protected Handler successor;
public void SetSuccessor(Handler successor)
{
this.successor = successor;
}
public abstract void HandleRequest(ResponsibilityContext context);
}
class ConcreteHandler1 : Handler
{
public override void HandleRequest(ResponsibilityContext context)
{
context.AuditRemark += "-饮料相关-";
if (context.Type == "饮料")
{
context.AuditResult = true;
this.Log("{0} 处理请求 {1}", this.GetType().Name, context);
}
else if (successor != null)
{
successor.HandleRequest(context);
}
}
}
class ConcreteHandler2 : Handler
{
public override void HandleRequest(ResponsibilityContext context)
{
context.AuditRemark += "-素食处理-";
if (context.Type == "素食")
{
context.AuditResult = true;
this.Log("{0} 处理请求 {1}", this.GetType().Name, context);
}
else if (successor != null)
{
successor.HandleRequest(context);
}
}
}
class ConcreteHandler3 : Handler
{
public override void HandleRequest(ResponsibilityContext context)
{
context.AuditRemark += "-肉类处理-";
if (context.Type == "肉类")
{
context.AuditResult = true;
this.Log("{0} 处理请求 {1}", this.GetType().Name, context);
}
else if (successor != null)
{
successor.HandleRequest(context);
}
}
}
调用
void Start()
{
ResponsibilityContext context = new ResponsibilityContext();
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
Handler handler3 = new ConcreteHandler3();
handler1.SetSuccessor(handler2);
handler2.SetSuccessor(handler3);
handler1.HandleRequest(context);
this.Log($"是否处理成功{context.AuditResult}");
this.Log($"AuditRemark:{context.AuditRemark}");
}
3.1.5 写法对比:
略
3.1.6 模式分析:
责任链的主要职责就是当客户提交一个请求时,此请求沿链传递至一个ConcreteHandler对象负责处理这个请求为止。
责任链方便的地方就是可随时增加或修改ConcreteHandler
。增强了给对象指派职责的灵活性。
需要注意的是,一个请求极有可能到了链的末端都不能得到处理,或者因为没有正确配置而得不到处理。
优点
- 请求的发送者和接收者解耦。
- 使得对象不需要知道链的结构。
- 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
缺点:
- 不能保证请求一定被处理。
- 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用(责任链收尾相交)。
- 可能不易观察运行时的特征,有碍于除错。
3.1.7 应用场景:
一个请求需要被多个对象逐步处理时。
3.1.8 小结:
责任链模式可以理解为elseif的优化版本,切记生搬硬套设计模式,适得其反。