场景:
一个学生,请事假或病假一天以下,只需要班主任同意即可;请事假2-3天或病假2-7天,需要学生处管理部门同意;请事假或病假天数超过前面的范围,或者请休学特殊假,都需要校长同意。
任务:
采用"职责链(Chain Of Responsibilit)设计模式,通过代码近似模拟上述场景。
UML类图:
参考代码:
using System; namespace RoleChain { //申请 class Request { //申请类别 private string requestType; public string RequestType { get { return requestType; } set { requestType = value; } } //申请内容 private string requestCause; public string RequestCause { get { return requestCause; } set { requestCause = value; } } //请假天数 private int dayNum; public int DayNum { get { return dayNum; } set { dayNum = value; } } } abstract class Role { protected string name; //角色的的上级角色 protected Role superior; public Role(string name) { this.name = name; } //设置角色的上级角色 public void SetSuperior(Role superior) { this.superior = superior; } //请假申请 abstract public void RequestApplications(Request request); } //学生角色 class StudentRole : Role { public StudentRole(string name) : base(name) { } public override void RequestApplications(Request request) { if (superior != null) superior.RequestApplications(request); } } //班主任角色 class FormteacherRole : Role { public FormteacherRole(string name) : base(name) { } public override void RequestApplications(Request request) { if (request.RequestType == "事假" && request.DayNum <= 1) { Console.WriteLine("原因:{1} 天数:{2} {0} 批准", name, request.RequestCause, request.DayNum); } else if (request.RequestType == "病假" && request.DayNum <= 1) { Console.WriteLine("原因:{1} 天数:{2} {0} 批准", name, request.RequestCause, request.DayNum); } else { if (superior != null) superior.RequestApplications(request); } } } //学生处角色 class StudentManagerRole : Role { public StudentManagerRole(string name) : base(name) { } public override void RequestApplications(Request request) { if (request.RequestType == "事假" && request.DayNum <= 3) { Console.WriteLine("原因:{1} 天数:{2} {0} 批准", name, request.RequestCause, request.DayNum); } else if (request.RequestType == "病假" && request.DayNum <= 7) { Console.WriteLine("原因:{1} 天数:{2} {0} 批准", name, request.RequestCause, request.DayNum); } else { if (superior != null) superior.RequestApplications(request); } } } //校长角色 class HeadmasterRole : Role { public HeadmasterRole(string name) : base(name) { } public override void RequestApplications(Request request) { if (request.RequestType == "事假" && request.DayNum <= 7) { Console.WriteLine(" 原因:{1} 天数:{2} {0}批准", name, request.RequestCause, request.DayNum); } else if (request.RequestType == "病假" && request.DayNum <= 120) { Console.WriteLine(" 原因:{1} 天数:{2} {0}批准", name, request.RequestCause, request.DayNum); } else if (request.RequestType == "休学") { Console.WriteLine("原因:{1} 天数:120 {0}批准", name, request.RequestCause); } else { Console.WriteLine("原因:{1} {0}拒", name, request.RequestCause); } } } class Program { static void Main(string[] args) { StudentRole stu = new StudentRole("学生"); FormteacherRole ft = new FormteacherRole("班主任"); StudentManagerRole man = new StudentManagerRole("学生管理处"); HeadmasterRole head = new HeadmasterRole("校长"); stu.SetSuperior(ft); ft.SetSuperior(man); man.SetSuperior(head); Request request = new Request(); request.RequestType = "事假"; request.RequestCause = "为班级采购物品"; request.DayNum = 1; stu.RequestApplications(request); Request request2 = new Request(); request2.RequestType = "事假"; request2.RequestCause = "回家取物品"; request2.DayNum= 2; stu.RequestApplications(request2); Request request3 = new Request(); request3.RequestType = "病假"; request3.RequestCause = "回家看病休学"; request3.DayNum= 5; stu.RequestApplications(request3); Request request4 = new Request(); request4.RequestType = "休学"; request4.RequestCause = "抑郁症"; request4.DayNum = 12; stu.RequestApplications(request4); Console.Read(); } } }
深度总结:
职责链模式定义:
为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
优点
- 降低了对象之间的耦合度 该模式降低了请求发送者和接收者的耦合度。
- 增强了系统的可扩展性 可以根据需要增加新的请求处理类,满足开闭原则。
- 增强了给对象指派职责的灵活性 当工作流程发生变化,可以动态地改变链内的成员或者修改它们的次序,也可动态地新增或者删除责任。
- 责任链简化了对象之间的连接 一个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
- 责任分担 每个类只需要处理自己该处理的工作,不能处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
缺点
- 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
- 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
- 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。