1.概念
职责链模式(Chain of Responsibility): 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
2.结构图
3.代码实现
c#
class Program
{
static void Main(string[] args)
{
var jinli = new CommonManager("经理");
var zonjian = new Majordomo("总监");
var zonjinli = new GeneralManager("总经理");
jinli.SetSuperior(zonjian); // 设置上级
zonjian.SetSuperior(zonjinli);
// 封装请求
var request = new Request();
request.Type = "请假";
request.Numbers = 3;
// 处理请求
jinli.HandleRequest(request);
}
}
// 封装请求,可进行自定义相关字段
public class Request
{
// 请求类型
public string Type { get; set; }
// 请求内容
public string Content { get; set; }
// 请求数量
public int Numbers { get; set; }
}
// 抽象父类,管理者
public abstract class Manager
{
protected string Name;
public Manager(string name)
{
Name = name;
}
// 关键角色,上级
protected Manager Superior;
// 设置上级
public void SetSuperior(Manager manager)
{
Superior = manager;
}
// 抽象方法,处理请求,供子类重写
public abstract void HandleRequest(Request request);
}
// 具体管理者,经理
public class CommonManager : Manager
{
public CommonManager(string name) : base(name)
{
}
public override void HandleRequest(Request request)
{
// 2天内的假期经理可以审批
if (request.Type == "请假" && request.Numbers <= 2)
{
Console.WriteLine("请假 {0} 天,批准人:{1}", request.Numbers, Name);
}
else if (Superior != null) // 其余申请转交上级进行处理
{
Superior.HandleRequest(request);
}
}
}
// 具体管理者,总监
public class Majordomo : Manager
{
public Majordomo(string name) : base(name)
{
}
public override void HandleRequest(Request request)
{
// 5天内的假期可以审批
if (request.Type == "请假" && request.Numbers <= 5)
{
Console.WriteLine("请假 {0} 天,批准人:{1}", request.Numbers, Name);
}
else if (Superior != null) // 其余申请转交上级进行处理
{
Superior.HandleRequest(request);
}
}
}
// 具体管理者,总经理
public class GeneralManager : Manager
{
public GeneralManager(string name) : base(name)
{
}
// 总经理可以处理所有请求
public override void HandleRequest(Request request)
{
// 任意数量的假期都可以审批
if (request.Type == "请假")
{
Console.WriteLine("{0},请假 {1} 天,批准人:{2}", request.Content, request.Numbers, Name);
}
else if (request.Type == "加薪" && request.Numbers <= 500) // 500 以内的加薪可以
{
Console.WriteLine("{0},加薪 {1},批准人:{2}", request.Content, request.Numbers, Name);
}else if (request.Type == "加薪" && request.Numbers > 500) // 超过 500 就要考虑一下
{
Console.WriteLine("{0},数量{1},再说吧", request.Content, request.Numbers);
}
}
}
4.职责链模式优缺点
4.1 优点
- 解耦发送者和接收者:职责链模式将发送者和接收者解耦,发送者无需知道请求将由哪个接收者处理,而接收者也无需知道请求的发送者是谁。这使得系统更加灵活,可以方便地进行组织和扩展。
- 可动态调整处理顺序:由于职责链模式的链条结构,可以动态地调整处理请求的顺序。可以根据需要添加、删除或修改链条中的处理者,以满足不同的业务需求。
- 可以处理复杂的请求处理逻辑:职责链模式可以将复杂的请求处理逻辑拆分成多个处理者,每个处理者专注于处理自己负责的部分。这样可以降低单个处理者的复杂性,使得代码更加清晰和可维护.
4.2 缺点
- 请求未必被处理:由于职责链模式的链条结构,请求可能会在链条的末尾无法被处理。如果没有适当地配置和管理链条,或者某个处理者没有正确地传递请求给下一个处理者,请求可能会被忽略或丢失。
- 可能导致性能问题:职责链模式的请求需要依次经过链条中的每个处理者,直到找到能够处理该请求的处理者为止。如果链条过长,或者每个处理者的处理逻辑复杂耗时,可能会导致性能问题。
- 可能难以调试:由于职责链模式将请求的处理逻辑分散在多个处理者中,当出现问题时,可能需要跟踪整个链条以确定请求的处理路径。这可能增加调试的复杂性。
5.职责链模式应用场景
- 日志记录系统:可以将日志记录系统设计为一个职责链,每个处理者负责处理一种类型的日志消息,例如错误日志、警告日志、信息日志等。请求会依次经过链条中的处理者,根据日志消息的类型进行处理和记录。
- 购买流程处理:在电子商务系统中,购买流程通常包括多个环节,例如验证库存、计算价格、生成订单等。可以使用职责链模式来处理购买请求,每个处理者负责处理一个环节,请求会依次经过链条中的处理者完成整个购买流程。
- 请求过滤器:在Web开发中,可以使用职责链模式来实现请求过滤器。每个过滤器可以对请求进行某种处理或验证,例如身份验证、参数检查、权限控制等。请求会依次经过过滤器链条,每个过滤器对请求进行处理或决定是否继续传递给下一个过滤器。
- 错误处理:在软件系统中,可以使用职责链模式来处理错误。每个处理者负责处理一种类型的错误,例如网络错误、数据库错误、文件错误等。请求会依次经过链条中的处理者,直到找到能够处理该错误的处理者为止。