模式开发之旅(20):职责链模式
2010-08-30 23:26:16之前介绍了模板模式、策略模式。今天来介绍职责链模式,这三种模式具有相同的作用:复用和扩展,在实际的项目开发中比较常用,特别是框架开发中,我们可以利用它们来提供框架的扩展点,能够让框架的使用者在不修改框架源码的情况下,基于扩展点定制化框架的功能。
职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
关于职责链模式,我们先来看看它的代码实现。结合代码实现,你会更容易理解它的定义。职责链模式有多种实现方式,比较常用的2种:
1. 利用链表实现
实现方式如下所示。其中,Handler 是所有处理器类的抽象父类,Handle() 是抽象方法。每个具体的处理器类(HandlerA、HandlerB)的 Handle() 方法的代码结构类似,如果它能处理该请求,就不继续往下传递;如果不能处理,则交由后面的处理器来处理(也就是调用 successor.Handle())。HandlerChain 是处理器链,从数据结构的角度来看,它就是一个记录了链头、链尾的链表。其中,记录链尾是为了方便添加处理器。
public abstract class Handler
{
protected Handler successor = null;
public void SetSuccessor(Handler successor)
{
this.successor = successor;
}
public abstract void Handle();
}
public class HandlerA : Handler {
public override void Handle()
{
bool handled = false;
//...
if (!handled && successor != null)
{
successor.Handle();
}
}
}
public class HandlerB : Handler
{
public override void Handle()
{
bool handled = false;
//...
if (!handled && successor != null)
{
successor.Handle();
}
}
}
public class HandlerChain
{
private Handler head = null;
private Handler tail = null;
public void AddHandler(Handler handler)
{
handler.SetSuccessor(null);
if (head == null)
{
head = handler;
tail = handler;
return;
}
tail.SetSuccessor(handler);
tail = handler;
}
public void Handle()
{
if (head != null)
{
head.Handle();
}
}
}
// 使用举例
public class Application
{
public static void main(string[] args)
{
HandlerChain chain = new HandlerChain();
chain.AddHandler(new HandlerA());
chain.AddHandler(new HandlerB());
chain.Handle();
}
}
实际上,上面的代码实现不够优雅。处理器类的 Handle() 方法,不仅包含自己的业务逻辑,还包含对下一个处理器的调用,也就是代码中的 successor.handle()。一个不熟悉这种代码结构的程序员,在添加新的处理器类的时候,很有可能忘记在 Handle() 方法中调用 successor.Handle(),这就会导致代码出现 bug。
针对这个问题,我们对代码进行重构,利用模板模式,将调用 successor.Handle() 的逻辑从具体的处理器类中剥离出来,放到抽象父类中。这样具体的处理器类只需要实现自己的业务逻辑就可以了。重构之后的代码如下所示:
public abstract class Handler
{
protected Handler successor = null;
public void SetSuccessor(Handler successor)
{
this.successor = successor;
}
public void Handle()
{
bool handled = DoHandle();
if (successor != null && !handled)
{
successor.Handle();
}
}
protected abstract bool DoHandle();
}
public class HandlerA : Handler {
protected override bool DoHandle()
{
bool handled = false;
//...
return handled;
}
}
public class HandlerB : Handler
{
protected override bool DoHandle()
{
bool handled = false;
//...
return handled;
}
}
public class HandlerChain
{
private Handler head = null;
private Handler tail = null;
public void AddHandler(Handler handler)
{
handler.SetSuccessor(null);
if (head == null)
{
head = handler;
tail = handler;
return;
}
tail.SetSuccessor(handler);
tail = handler;
}
public void Handle()
{
if (head != null)
{
head.Handle();
}
}
}
// 使用举例
public class Application
{
public static void main(string[] args)
{
HandlerChain chain = new HandlerChain();
chain.AddHandler(new HandlerA());
chain.AddHandler(new HandlerB());
chain.Handle();
}
}
利用数组实现
我们再来看第二种实现方式,代码如下所示。这种实现方式更加简单。HandlerChain 类用数组而非链表来保存所有的处理器,并且需要在 HandlerChain 的 Handle() 方法中,依次调用每个处理器的 Handle() 方法。
public interface IHandler
{
bool Handle();
}
public class HandlerA : IHandler
{
public bool Handle()
{
bool handled = false;
//...
return handled;
}
}
public class HandlerB : IHandler
{
public bool Handle()
{
bool handled = false;
//...
return handled;
}
}
public class HandlerChain
{
private List<IHandler> handlers = new List<IHandler>();
public void AddHandler(IHandler handler)
{
handlers.Add(handler);
}
public void Handle()
{
foreach (var item in handlers)
{
bool handled = item.Handle();
if (handled) break;
}
}
}
// 使用举例
public class Application
{
public static void main(string[] args)
{
HandlerChain chain = new HandlerChain();
chain.AddHandler(new HandlerA());
chain.AddHandler(new HandlerB());
chain.Handle();
}
}
在 GoF 给出的定义中,如果处理器链上的某个处理器能够处理这个请求,那就不会继续往下传递请求。实际上,职责链模式还有一种变体,那就是请求会被所有的处理器都处理一遍,不存在中途终止的情况。这种变体也有两种实现方式:用链表存储处理器和用数组存储处理器,跟上面的两种实现方式类似,只需要稍微修改即可。
这里只给出其中一种实现方式,如下所示
public abstract class Handler
{
protected Handler successor = null;
public void SetSuccessor(Handler successor)
{
this.successor = successor;
}
public void Handle()
{
DoHandle();
if (successor != null)
{
successor.Handle();
}
}
protected abstract void DoHandle();
}
public class HandlerA : Handler {
protected override void DoHandle()
{
//...
}
}
public class HandlerB : Handler
{
protected override void DoHandle()
{
//...
}
}
public class HandlerChain
{
private Handler head = null;
private Handler tail = null;
public void addHandler(Handler handler)
{
handler.SetSuccessor(null);
if(head == null)
{
head = handler;
tail = handler;
return;
}
tail.SetSuccessor(handler);
tail = handler;
}
public void Handle()
{
if (head != null)
{
head.Handle();
}
}
}
// 使用举例
public class Application
{
public static void main(string[] args)
{
HandlerChain chain = new HandlerChain();
chain.addHandler(new HandlerA());
chain.addHandler(new HandlerB());
chain.Handle();
}
}