責任鏈設計模式,是行為型設計模式的巔峰之作。 現在有一個場景,請假申請。請假時間的長短,需要不同級別的領導才能審批。 萬物皆對象嘛,請假需要工號、姓名、原因、時長、結果等等,那我們來定義一個請假的類。其實其就是一個上下文環境(Context),保存業務處理中參數 中間結果 最終結果。行為型設計模式重 ...
責任鏈設計模式,是行為型設計模式的巔峰之作。
現在有一個場景,請假申請。請假時間的長短,需要不同級別的領導才能審批。
萬物皆對象嘛,請假需要工號、姓名、原因、時長、結果等等,那我們來定義一個請假的類。其實其就是一個上下文環境(Context),保存業務處理中參數-----中間結果-----最終結果。行為型設計模式重用的標配,把行為轉移。
public class ApplyContext { public int Id { get; set; } public string Name { get; set; } /// <summary> /// 請假時長 /// </summary> public int Hour { get; set; } public string Description { get; set; } public bool AuditResult { get; set; } public string AuditRemark { get; set; } }
請假需要new一個實例:
ApplyContext context = new ApplyContext() { Id = 506, Name = "bingle", Hour = 100, Description = "世界那麼大,我想去看看!", AuditResult = false, AuditRemark = "" };
第一種方式,審批邏輯都卸載上端,直接就是需求翻譯,沒有任何加工,談不上什麼擴展,面向國產:
if (context.Hour <= 8) { Console.WriteLine("PM審批通過"); } else if (context.Hour <= 16) { Console.WriteLine("主管審批通過"); } else { Console.WriteLine("************"); }
第二種方式,面向對象:封裝--繼承--多態,轉移業務邏輯,也只是一個翻譯機,翻譯完+面向對象,其實完全沒有涉及加工沒有思考。
領導類S:
public class PM { public override void Audit(ApplyContext context) { Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit"); if (context.Hour <= 8) { context.AuditResult = true; context.AuditRemark = "允許請假!"; } } } public class Charge { public override void Audit(ApplyContext context) { Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit"); if (context.Hour <= 16) { context.AuditResult = true; context.AuditRemark = "允許請假!"; } } } public class Manager { public override void Audit(ApplyContext context) { Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit"); if (context.Hour <= 24) { context.AuditResult = true; context.AuditRemark = "允許請假!"; } } } public class Chief { public override void Audit(ApplyContext context) { Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit"); if (context.Hour <= 48) { context.AuditResult = true; context.AuditRemark = "允許請假!"; } } } public class CEO : AbstractAuditor { public override void Audit(ApplyContext context) { Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit"); if (context.Hour <= 96) { context.AuditResult = true; context.AuditRemark = "允許請假!"; } } } public class ChiarMan : AbstractAuditor { public override void Audit(ApplyContext context) { Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit"); if (context.Hour <= 1000000) { context.AuditResult = true; context.AuditRemark = "允許請假!"; } } }View Code
下麵進行邏輯的翻譯:
AbstractAuditor pm = new PM() { Name = "bingle1" }; pm.Audit(context); if (!context.AuditResult) { AbstractAuditor charge = new Charge() { Name = "bingle2" }; charge.Audit(context); if (!context.AuditResult) { AbstractAuditor manager = new Manager() { Name = "bingle3" }; manager.Audit(context); if (!context.AuditResult) { //找下一環節 } } }
不要直接翻譯的邏輯,需要涉及,現在的場景分析是,1、許可權範圍內,審批通過;2、許可權範圍外,交給下一環節審批,寫的代碼又多了一個,指定洗衣環節,甩鍋大法開始。
首先定義一個抽象父類:
public abstract class AbstractAuditor { public string Name { get; set; } public abstract void Audit(ApplyContext context); private AbstractAuditor _NextAuditor = null; public void SetNext(AbstractAuditor auditor) { this._NextAuditor = auditor; } protected void AuditNext(ApplyContext context) { if (this._NextAuditor != null) { this._NextAuditor.Audit(context); } else { context.AuditResult = false; context.AuditRemark = "不允許請假!"; } } }
領導類需要繼承這個抽象類:
public class PM : AbstractAuditor { public override void Audit(ApplyContext context) { Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit"); if (context.Hour <= 8) { context.AuditResult = true; context.AuditRemark = "允許請假!"; } else { AbstractAuditor charge = new Charge() { Name = "象撲君" }; charge.Audit(context); } } }
其他的領導類以此類推.....
調用的時候,只需要找最低許可權的人,去審批
AbstractAuditor pm = new PM() { Name = "bingle" }; pm.Audit(context);
以上,轉移了申請提交的邏輯,這次符合實際情況,有了自己的思考和設計在裡面。
甩鍋大法開始了,一樣,領導類需要實現抽象父類,不過在Audit方法中稍作了改動
public class PM : AbstractAuditor { public override void Audit(ApplyContext context) { Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit"); if (context.Hour <= 8) { context.AuditResult = true; context.AuditRemark = "允許請假!"; } else { base.AuditNext(context); } } } public class Manager : AbstractAuditor { public override void Audit(ApplyContext context) { Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit"); if (context.Hour <= 24) { context.AuditResult = true; context.AuditRemark = "允許請假!"; } else { base.AuditNext(context); } } } public class Chief : AbstractAuditor { public override void Audit(ApplyContext context) { Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit"); if (context.Hour <= 48) { context.AuditResult = true; context.AuditRemark = "允許請假!"; } else { base.AuditNext(context); } } } public class ChiarMan : AbstractAuditor { public override void Audit(ApplyContext context) { Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit"); if (context.Hour <= 1000000) { context.AuditResult = true; context.AuditRemark = "允許請假!"; } else { base.AuditNext(context); } } } public class Charge: AbstractAuditor { public override void Audit(ApplyContext context) { Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit"); if (context.Hour <= 16) { context.AuditResult = true; context.AuditRemark = "允許請假!"; } else { base.AuditNext(context); } } } public class CEO : AbstractAuditor { public override void Audit(ApplyContext context) { Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit"); if (context.Hour <= 96) { context.AuditResult = true; context.AuditRemark = "允許請假!"; } else { base.AuditNext(context); } } }View Code
下麵需要找領導審批了:
AbstractAuditor pm = new PM() { Name = "bingle1" }; AbstractAuditor charge = new Charge() { Name = "bingle1" }; AbstractAuditor manager = new Manager() { Name = "bingle1" }; AbstractAuditor chief = new Chief() { Name = "bingle1" }; AbstractAuditor ceo = new CEO() { Name = "bingle1" }; //pm.SetNext(charge); //charge.SetNext(manager); pm.SetNext(manager); manager.SetNext(chief); chief.SetNext(ceo); ceo.SetNext(new ChiarMan() { Name = "bingle1" }); //流程的可擴展 pm.Audit(context); if (!context.AuditResult) { Console.WriteLine("不幹了!"); }
以上,把流暢環節邏輯從業務類轉移了。