消息模式在实际开发应用中的优势
曾經(jīng).NET面試過(guò)程中經(jīng)常問(wèn)的一個(gè)問(wèn)題是,如果程序集A,引用B ,B 引用C,那么C怎么去訪問(wèn)A中的方法呢。
這個(gè)問(wèn)題初學(xué).net可能一時(shí)想不出該咋處理,這涉及到循環(huán)引用問(wèn)題。但有點(diǎn)經(jīng)驗(yàn)的可能就簡(jiǎn)單了,通過(guò)委托的方式,從A中傳遞到C中,然后在C中就可以訪問(wèn)了。還有通過(guò)接口方式也可以。
但是如果項(xiàng)目中有非常多的程序集, A B C D E F G 而且互相都有交叉的訪問(wèn)關(guān)系,任何兩者都有可能訪問(wèn),那么如果用接口和委托可能就不是那么方便了。
?
消息模式不僅僅可以完美解決上述問(wèn)題,還可以使得所有交互都集中處理,使用更方便。
最近開發(fā)的一個(gè)系統(tǒng),涉及到諸多數(shù)據(jù)處理以及控制層,而且之間大都存在循環(huán)訪問(wèn)的問(wèn)題,如果不用消息模式,系統(tǒng)將變得非常難于維護(hù)。
系統(tǒng)有如下幾層:UI層,指令層,數(shù)據(jù)層,算法層,狀態(tài)層。?
UI層需要通知指令層參數(shù)變更等。指令層需要通知UI層,發(fā)出買入賣出操作并且更改UI顯示。
狀態(tài)層狀態(tài)改變后,需要通知UI層顯示變更,指令層訪問(wèn)算法層,指令層執(zhí)行算法發(fā)現(xiàn)滿足條件時(shí),通知狀態(tài)層變更。狀態(tài)層狀態(tài)變更后,通知指令層狀態(tài)變更正常或者異常。然后進(jìn)一步后續(xù)操作
還有自定義控件需要訪問(wèn)Form中的方法以及給form發(fā)送通知都是通過(guò)發(fā)送消息的方式來(lái)實(shí)現(xiàn)的。
?
項(xiàng)目結(jié)構(gòu)以及數(shù)據(jù)控制流圖如下(數(shù)據(jù)控制流只標(biāo)記了部分,實(shí)際流更多)
? ??
?
?
消息中心 主要包括兩個(gè)靜態(tài)方法,一個(gè)公共事件,這里負(fù)責(zé)系統(tǒng)中所有的事件訂閱以及事件觸發(fā)的樞紐
namespace Common {/// <summary>/// 消息事件參數(shù)/// </summary>public class MessageArg : EventArgs{/// <summary>/// 消息類型/// </summary>public EnumMsgtype mstType { set; get; }public string gpCode { set; get; }public string message { set; get; }/// <summary>/// 擴(kuò)展數(shù)據(jù)/// </summary>public object ExtendData { set; get; }}public class MessageCenter{ public static MessageCenter Instanse = null;static MessageCenter(){Instanse = new MessageCenter();}public delegate void MessageHandle(Object sender, MessageArg e);/// <summary>/// 消息事件/// </summary>public event MessageHandle OnMessage;/// <summary>/// 發(fā)送事件(后續(xù)添加的,發(fā)現(xiàn)消息模式的諸多便利)/// </summary>/// <param name="gpCode"></param>/// <param name="eventType"></param>/// <param name="extendData"></param>public static void SendEvent(string gpCode,EnumMsgtype eventType, object extendData){if(MessageCenter.Instanse.OnMessage!=null){try{MessageCenter.Instanse.OnMessage(MessageCenter.Instanse, new MessageArg() { mstType = eventType, gpCode = gpCode, ExtendData = extendData });}catch(Exception ex){ShowExceptionMsg(ex, gpCode);}} }/// <summary>/// 提示信息(一開始設(shè)計(jì)僅僅是想發(fā)送消息)/// </summary>/// <param name="mstType"></param>/// <param name="gpCode"></param>/// <param name="message"></param>public static void ShowMessage(EnumMsgtype mstType, string gpCode, string message){if (MessageCenter.Instanse.OnMessage != null){MessageCenter.Instanse.OnMessage(MessageCenter.Instanse, new MessageArg() { mstType = mstType, gpCode = gpCode, message = message });}}/// <summary>/// 發(fā)送異常信息/// </summary>/// <param name="ex"></param>/// <param name="gpCode"></param>public static void ShowExceptionMsg(Exception ex, string gpCode){EnumMsgtype msgType;string msg = "";if (ex is ApplicationException){msgType = EnumMsgtype.ImportantInfo;msg = ex.Message;}else{msgType = EnumMsgtype.SysError;msg = ex.ToString();}ShowMessage(msgType, gpCode, msg);}} }?
?
指令中心 發(fā)送通知舉例
MessageCenter.SendEvent(singleStatus.GpCode, EnumMsgtype.ManageBeforeChangeEvent, singleStatus);//觸發(fā)操作前事件MessageCenter.SendEvent(singleStatus.GpCode, EnumMsgtype.ManageChangeEvent, singleStatus);//觸發(fā)操作后事件
private void SetGpBuy(PriceTimeModel gpRealTimeData, GpStatusManage gpStatus){//所有需要買的狀態(tài)項(xiàng)List<GpStatusBase> lstBuyStatus = gpStatus.AllNeedBuyStatus;//依次進(jìn)行驗(yàn)證操作foreach (var singleStatus in lstBuyStatus){//設(shè)置狀態(tài)的最后一個(gè)股票信息singleStatus.LasterOpraPriceItem = gpRealTimeData;//獲取股票算法ManageRuleBase saleRule = ManageRuleBase.GetRule(gpStatus.GpParameterItem.LogicType);saleRule.PriceChange(gpRealTimeData, singleStatus); bool isCanBuy = CheckCanBuy(gpRealTimeData, singleStatus, saleRule);if (isCanBuy){MessageCenter.SendEvent(singleStatus.GpCode, EnumMsgtype.ManageBeforeChangeEvent, singleStatus);//緊急暫停if (IsStopBuy || singleStatus.GpItem.IsStopBuy){MessageCenter.ShowMessage(EnumMsgtype.StatusInfo, singleStatus.GpCode, gpRealTimeData.GetGpcodeAndTimeStr() + singleStatus.ManageTypeName + "緊急暫停,取消買操作");continue;}//的判斷是上面這個(gè)事件可能會(huì)更改狀態(tài)if (singleStatus.CanManage == false || singleStatus.ManageCnt==0){MessageCenter.ShowMessage(EnumMsgtype.StatusInfo, singleStatus.GpCode, gpRealTimeData.GetGpcodeAndTimeStr() + singleStatus.ManageTypeName + "數(shù)量不足,取消買操作");continue;}//發(fā)出買指令(鎖定價(jià)格買)var para = new ManageParameter(){GpCode = singleStatus.GpItem.GpCode,InstructWay = EnumInstruct.Buy,ManagePrice = singleStatus.LockPrice + gpStatus.GpItem.ChangePersontToPrice(0.2f),//加上0.3百分點(diǎn)增加買入成功率 //0322還是更改鎖定價(jià)格+0.2fManageCnt = singleStatus.ManageCnt,PriceItem = gpRealTimeData,GpItem = singleStatus.GpItem};//外掛操作if (waiguaOprationer.GpManage(para)){float managePrice = gpRealTimeData.Price + gpStatus.GpItem.ChangePersontToPrice(0.2f);singleStatus.ManagePrice = float.Parse(managePrice.ToString("f2"));singleStatus.ManagePriceItem = gpRealTimeData;//買入,更改狀態(tài) singleStatus.SetGpStatusAfterEvent(EnumOprationStatus.Buyed);lstNeedCheckStatus.Add(singleStatus);//通知 MessageCenter.ShowMessage(EnumMsgtype.StatusInfo, gpStatus.GpCode, gpRealTimeData.GetGpcodeAndTimeStr() + singleStatus.ManageTypeName+ "買入操作成功,待驗(yàn)證\r\n");//操作變更事件 MessageCenter.SendEvent(singleStatus.GpCode, EnumMsgtype.ManageChangeEvent, singleStatus);}}}}
?
UI接收消息舉例
訂閱消息?MessageCenter.Instanse.OnMessage += Instanse_OnMessage;
對(duì)不同的消息類型分別處理
private void Instanse_OnMessage(object sender, MessageArg e){try{if (GpItem != null && e.gpCode == ""){//清空if (e.mstType == EnumMsgtype.ClearDataEvent){this.lstOnePara.ForEach(t =>{t.SingleStatus = null;t.ReinitStepStyle();});}}if (GpItem != null && e.gpCode == GpItem.GpCode){//如果不在Form控制下,那么取消事件注冊(cè)!!!var parFrm = FindParentForm();if (parFrm == null){//這里通常是由于導(dǎo)入了參數(shù),導(dǎo)致的額外注冊(cè)MessageCenter.Instanse.OnMessage -= Instanse_OnMessage;return;}if (e.mstType == EnumMsgtype.PriceChangeEvent){// }//消息else if (e.mstType == EnumMsgtype.Info || e.mstType == EnumMsgtype.ImportantInfo || e.mstType == EnumMsgtype.StatusInfo){// }else if (e.mstType == EnumMsgtype.ManageBeforeChangeEvent)//操作之前事件 {// }else if (e.mstType == EnumMsgtype.ManageChangeEvent)//操作之后事件 {// }else if (e.mstType == EnumMsgtype.AutoLockChangeEvent)//智能鎖定 {// }else if(e.mstType== EnumMsgtype.MonitStartEvent){// } }}catch(Exception ex){MessageCenter.ShowExceptionMsg(ex, GpItem.GpCode);}}?
文中的舉例的軟件以及下載地址在我另外一博文中介紹
http://www.cnblogs.com/blackvis/p/5779443.html
?
總結(jié)消息模式的幾大優(yōu)點(diǎn)
1 解決程序集循環(huán)訪問(wèn)的問(wèn)題
2 程序集解耦,對(duì)于少量通信的程序集之間不需要存在引用關(guān)系,就可達(dá)到互相通訊,亦可減少程序集中的public方法數(shù)量。
3 消息以廣播的形式進(jìn)行發(fā)送,使得一處發(fā)送,多處重復(fù)使用。
4 消息集中處理控制更加靈活。
?
轉(zhuǎn)載于:https://www.cnblogs.com/blackvis/p/5782288.html
總結(jié)
以上是生活随笔為你收集整理的消息模式在实际开发应用中的优势的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 导入jasperreports出现Can
- 下一篇: Python爬虫之JS逆向分析技巧