定义
避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。
举例
像大公司发工资,需要层层审核,从最顶层董事长——>总经理->财务总监....,像链式结构一样
结构
实现
//定义处理请示的接口
abstract class Handler
{
protected Handler successor;
//设置继任者
public void SetSuccessor(Handler successor)
{
this.successor = successor;
}
public abstract void HandleRequest(int reqquest);
}
//ConcreteHandler类,具体处理者类,处理它所负责的请求,可访问它的后继者,如果可处理该请求,就处理之,否则就将该请求转发给它的后继者。
//ConcreteHandler1,当请求数在0到10之间则有权处理,否则转到下一位。
class ConcreteHandler1 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 0 && request < 10)
{
Console.WriteLine("[0}处理请求{ 1}", this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
//ConcreteHandler2,当请求数在10到20之间则有权处理,否则转到下一位。
class ConcreteHandler2 : Handler
{
public override void HandleRequest(int request)
{
//处理10-20
if (request >= 10 && request < 20)
{
Console.WriteLine("{0}处理请求{1}", this.GetType().Name, request);
}
else if (successor != null)
{
//转移到下一位
successor.HandleRequest(request);
}
}
}
//ConcreteHandler3,当请求数在20到30之间则有权处理,否则转到下一位。
class ConcreteHandler3 : Handler
{
public override void HandleRequest(int request)
{
//处理20-30
if (request >= 20 && request < 30)
{
Console.WriteLine(" {O}处理请求{ 1}", this.GetType().Name, request);
}
else if (successor != null)
{
//转移到下一位
successor.HandleRequest(request);
}
}
}
class Program
{
static void Main(string[] args)
{
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);
}
}
}
优点
- (1)职责链模式使得一个对象无须知道是其他哪一个对象处理其请求,仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息﹐且链中的对象不需要知道链的结构,由客户端负责链的创建,降低了系统的耦合度。
- (2)请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理者的引用,可简化对象之间的相互连接。
- (3)在给对象分配职责时,职责链可以带来更多的灵活性,可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的职责。
- (4)在系统中增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新建链即可,从这一点来看是符合开闭原则的。
缺点
- (1)由于一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理;一个请求也可能因职责链没有被正确配置而得不到处理。
- (2)对于比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定的影响,而且在进行代码调试时不太方便。
- (3)如果建链不当,可能会造成循环调用,导致系统陷入死循环。
适用环境
- (1)有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定,客户端只需将请求提交到链上,而无须关心请求的处理对象是谁以及它是如何处理的。
- (2)在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- (3)可动态指定一组对象处理请求,客户端可以动态地创建职责链来处理请求,还可以改变链中处理者之间的先后次序。