一:現實場景
有時候在開發的過程中,我們經常會根據某個狀態的值,寫出很多的ifelse邏輯,比如拿專案裡面的案例來說,如果當前傳送的是彩信,此種狀態需要如何給
實體賦值,如果是簡訊,郵件又是其他方式的賦值,等等此類,這種情況下一般會寫出如下if判斷,對吧,真實程式碼如下:
1 if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.郵件)) 2 { 3 //第三步:動態生成郵件模板 4 var styleInfo = CacheUtil.GetRandomEmailStyle(); 5 6 var tuple = new EdmDraftBoxBLL().GetEdmHtmlTitle(communicationInfo.EDMJson, styleInfo.StyleId); 7 8 leaflet.Title = tuple.Item1; 9 leaflet.EDMContent = tuple.Item2; 10 leaflet.Header = tuple.Item3; 11 leaflet.SendSMSCount = 1; 12 } 13 14 if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.簡訊)) 15 { 16 leaflet.SMSContent = communicationInfo.SMSContent; 17 leaflet.SendSMSCount = communicationInfo.SMSCount; 18 } 19 20 21 if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.彩信)) 22 { 23 leaflet.MMSContent = communicationInfo.MMSContent; 24 }
上面的程式碼還是非常簡單明瞭的,程式會根據leaflet.CommunicationtypeEnum的不同做不同的判斷,比如說當前狀態是郵件的話,程式會從30套郵件
模板庫中隨機抽取一封,給leaflet的title,header...賦值,有些人可能會說這段程式碼不難看哈,確實是這樣,但是如果面對需求變更呢?比如說後期需要增加微
信,微博渠道,那是不是又要加上兩個if才能把這個問題解決呢? 這就違背了設計模式中開閉原則,對吧,面對這種場景,可以用責任鏈模式擺平。
二:責任鏈模式
責任鏈模式講的就是將請求的傳送者和接收者進行分離,避免請求傳送者與接收者耦合在一起,讓多個物件都有可能接收請求,將這些物件連線成一條鏈,
並且沿著這條鏈傳遞請求,直到有物件處理它為止,面對需求變更,只需要更加處理類就好了,而且客戶端可以按照自己的需求拼接處理鏈條,是不是很強大。
1. AbstractComunication
public abstract class AbstractComunication { AbstractComunication abstractComunication = null; public void SetHandler(AbstractComunication abstractComunication) { this.abstractComunication = abstractComunication; } public abstract void HanderRequest(LeafletEntity leaflet, EventmarketingSmsEdmContentInfo communicationInfo); }
2. MMSComunication
1 public class MMSComunication : AbstractComunication 2 { 3 public override void HanderRequest(LeafletEntity leaflet, EventmarketingSmsEdmContentInfo communicationInfo) 4 { 5 if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.彩信)) 6 { 7 leaflet.MMSContent = communicationInfo.MMSContent; 8 } 9 else 10 { 11 abstractComunication.HanderRequest(leaflet, communicationInfo); 12 } 13 } 14 }
3.EDMComunication
1 public class EDMComunication : AbstractComunication 2 { 3 public override void HanderRequest(LeafletEntity leaflet, EventmarketingSmsEdmContentInfo communicationInfo) 4 { 5 if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.郵件)) 6 { 7 //第三步:動態生成郵件模板 8 var styleInfo = CacheUtil.GetRandomEmailStyle(); 9 10 var tuple = new EdmDraftBoxBLL().GetEdmHtmlTitle(communicationInfo.EDMJson, styleInfo.StyleId); 11 12 leaflet.Title = tuple.Item1; 13 leaflet.EDMContent = tuple.Item2; 14 leaflet.Header = tuple.Item3; 15 leaflet.SendSMSCount = 1; 16 } 17 else 18 { 19 abstractComunication.HanderRequest(leaflet, communicationInfo); 20 } 21 } 22 }
4.SMSComunication
1 public class SMSComunication : AbstractComunication 2 { 3 public override void HanderRequest(LeafletEntity leaflet, EventmarketingSmsEdmContentInfo communicationInfo) 4 { 5 if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.簡訊)) 6 { 7 leaflet.SMSContent = communicationInfo.SMSContent; 8 leaflet.SendSMSCount = communicationInfo.SMSCount; 9 } 10 else 11 { 12 abstractComunication.HanderRequest(leaflet, communicationInfo); 13 } 14 } 15 }
5.客戶端呼叫
1 AbstractComunication communication1 = new EDMComunication(); 2 AbstractComunication communication2 = new SMSComunication(); 3 AbstractComunication communication3 = new MMSComunication(); 4 5 //手工將三個Comunication 憑藉成一個鏈條,形成單連結串列的模型 6 communication1.SetHandler(communication2); 7 communication2.SetHandler(communication3); 8 9 communication1.HanderRequest(leaflet, communicationInfo);
其實上面的程式碼,需要繞一下腦子的就是如何通過SetHandler將三個xxxComunication拼接成一個單連結串列的形式,連結串列怎麼拼接在於客戶端如何設定sethandler,
靈活性完全就在客戶端這邊,然後就非常方便將leaflet在責任鏈中游走,最終會被某一狀態處理邏輯處理,講到這裡,我想大家應該都知道責任鏈模式是幹嘛的了,
由於是真實案例就不方便跑程式碼了,下面我構建一個責任鏈模型,大家比照一下就可以了,是不是有種請求和處理的分離,而且我還可以根據需要組合我的責任鏈,
其實js的冒泡機制就是這種模式的一個體現。
public abstract class AbstractHandler { protected AbstractHandler abstractHandler = null; public void SetHandler(AbstractHandler abstractHandler) { this.abstractHandler = abstractHandler; } public virtual void HandleRequest(int request) { } } public class ConcreteHandler1 : AbstractHandler { public override void HandleRequest(int request) { if (request == 1) { Console.WriteLine("handler1 給你處理了"); } else { abstractHandler.HandleRequest(request); } } } public class ConcreteHandler2 : AbstractHandler { public override void HandleRequest(int request) { if (request == 2) { Console.WriteLine("handler2 給你處理了"); } else { abstractHandler.HandleRequest(request); } } } public class ConcreteHandler3 : AbstractHandler { public override void HandleRequest(int request) { if (request == 3) { Console.WriteLine("handler3 給你處理了"); } else { abstractHandler.HandleRequest(request); } } } class Program { static void Main(string[] args) { AbstractHandler hander1 = new ConcreteHandler1(); AbstractHandler hander2 = new ConcreteHandler2(); AbstractHandler hander3 = new ConcreteHandler3(); hander1.SetHandler(hander2); hander2.SetHandler(hander3); hander1.HandleRequest(3); } }
好了,模板和實際專案的案例都給大家展示了,希望能幫助到你。