意图
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
适用性
在以下条件下使用:
- 有多个对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
- 你想在不明确指定接受者的情况下,向多个对象中的一个提交一个请求。
- 可处理一个请求的对象集合应该被动态指定。
结构
实现
实现一个邮件处理系统,将邮件按照类别交给不同的对象处理。
已经分类的邮件
public class Request
{
public Request(string type)
{
Type = type;
}
private string _content;
public string Type { get; set; }
}
处理的抽象,类似链表,自身包含指向下一个处理节点的对象
public abstract class Handler
{
protected Handler _nextHandler;
public abstract void ProcessRequest(Request request);
public void SetNext(Handler handler)
{
_nextHandler = handler;
}
}
对不同类型进行处理的对象
//粉丝邮件处理
public class FanHandler:Handler
{
public override void ProcessRequest(Request request)
{
if (request.Type=="fan")
{
Console.WriteLine("fan's email process");
}
else
{
_nextHandler.ProcessRequest(request);
}
}
}
//垃圾邮件处理
public class SpamHandler : Handler
{
public override void ProcessRequest(Request request)
{
if (request.Type == "spam")
{
Console.WriteLine("spam delete");
}
else
{
_nextHandler.ProcessRequest(request);
}
}
}
//抱怨和意见邮件处理
public class ComplaintHandler:Handler
{
public override void ProcessRequest(Request request)
{
if (request.Type=="complaint")
{
Console.WriteLine("complaint process");
}
else
{
_nextHandler.ProcessRequest(request);
}
}
}
//其他邮件处理
public class DefaultHandler:Handler
{
public override void ProcessRequest(Request request)
{
Console.WriteLine("Do some thing!");
}
}
使用之前,先要将责任链串联起来
class Program
{
static void Main(string[] args)
{
//发送者
var fan = new Request("fan");
var spam = new Request("spam");
var complaint = new Request("complaint");
var other = new Request("other");
//接受者
var fanHandler = new FanHandler();
var spamHandler = new SpamHandler();
var complaintHandler = new ComplaintHandler();
var defaultHandler = new DefaultHandler();
//构造责任链
fanHandler.SetNext(spamHandler);
spamHandler.SetNext(complaintHandler);
complaintHandler.SetNext(defaultHandler);
//请求交由责任链头节点处理
fanHandler.ProcessRequest(fan);
fanHandler.ProcessRequest(spam);
fanHandler.ProcessRequest(complaint);
fanHandler.ProcessRequest(other);
Console.ReadKey();
}
}
运行结果
效果
- 降低耦合度
- 增强了给对象指派职责的灵活性
- 不保证被接受(用一个默认处理类来解决这个问题)