消息模式在实际开发应用中的优势

曾经.NET面试过程中经常问的一个问题是,如果程序集A,引用B ,B 引用C,那么C怎么去访问A中的方法呢。

这个问题初学.net可能一时想不出该咋处理,这涉及到循环引用问题。但有点经验的可能就简单了,通过委托的方式,从A中传递到C中,然后在C中就可以访问了。还有通过接口方式也可以。

但是如果项目中有非常多的程序集, A B C D E F G 而且互相都有交叉的访问关系,任何两者都有可能访问,那么如果用接口和委托可能就不是那么方便了。

 

消息模式不仅仅可以完美解决上述问题,还可以使得所有交互都集中处理,使用更方便。

最近开发的一个系统,涉及到诸多数据处理以及控制层,而且之间大都存在循环访问的问题,如果不用消息模式,系统将变得非常难于维护。

系统有如下几层:UI层,指令层,数据层,算法层,状态层。 

UI层需要通知指令层参数变更等。指令层需要通知UI层,发出买入卖出操作并且更改UI显示。

状态层状态改变后,需要通知UI层显示变更,指令层访问算法层,指令层执行算法发现满足条件时,通知状态层变更。状态层状态变更后,通知指令层状态变更正常或者异常。然后进一步后续操作

还有自定义控件需要访问Form中的方法以及给form发送通知都是通过发送消息的方式来实现的。

 

项目结构以及数据控制流图如下(数据控制流只标记了部分,实际流更多)

    

 

 

消息中心 主要包括两个静态方法,一个公共事件,这里负责系统中所有的事件订阅以及事件触发的枢纽

namespace Common
{/// <summary>/// 消息事件参数/// </summary>public class MessageArg : EventArgs{/// <summary>/// 消息类型/// </summary>public EnumMsgtype mstType { set; get; }public string gpCode { set; get; }public string message { set; get; }/// <summary>/// 扩展数据/// </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>/// 发送事件(后续添加的,发现消息模式的诸多便利)/// </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>/// 提示信息(一开始设计仅仅是想发送消息)/// </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>/// 发送异常信息/// </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);}}
}

 

 

指令中心 发送通知举例

MessageCenter.SendEvent(singleStatus.GpCode, EnumMsgtype.ManageBeforeChangeEvent, singleStatus);//触发操作前事件
MessageCenter.SendEvent(singleStatus.GpCode, EnumMsgtype.ManageChangeEvent, singleStatus);//触发操作后事件

  private void SetGpBuy(PriceTimeModel gpRealTimeData, GpStatusManage gpStatus){//所有需要买的状态项List<GpStatusBase> lstBuyStatus = gpStatus.AllNeedBuyStatus;//依次进行验证操作foreach (var singleStatus in lstBuyStatus){//设置状态的最后一个股票信息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;}//的判断是上面这个事件可能会更改状态if (singleStatus.CanManage == false || singleStatus.ManageCnt==0){MessageCenter.ShowMessage(EnumMsgtype.StatusInfo, singleStatus.GpCode, gpRealTimeData.GetGpcodeAndTimeStr() + singleStatus.ManageTypeName + "数量不足,取消买操作");continue;}//发出买指令(锁定价格买)var para = new ManageParameter(){GpCode = singleStatus.GpItem.GpCode,InstructWay = EnumInstruct.Buy,ManagePrice = singleStatus.LockPrice + gpStatus.GpItem.ChangePersontToPrice(0.2f),//加上0.3百分点增加买入成功率 //0322还是更改锁定价格+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;//买入,更改状态
                        singleStatus.SetGpStatusAfterEvent(EnumOprationStatus.Buyed);lstNeedCheckStatus.Add(singleStatus);//通知
                        MessageCenter.ShowMessage(EnumMsgtype.StatusInfo, gpStatus.GpCode, gpRealTimeData.GetGpcodeAndTimeStr() + singleStatus.ManageTypeName+ "买入操作成功,待验证\r\n");//操作变更事件
                        MessageCenter.SendEvent(singleStatus.GpCode, EnumMsgtype.ManageChangeEvent, singleStatus);}}}}

 

UI接收消息举例

订阅消息 MessageCenter.Instanse.OnMessage += Instanse_OnMessage;

对不同的消息类型分别处理

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控制下,那么取消事件注册!!!var parFrm = FindParentForm();if (parFrm == null){//这里通常是由于导入了参数,导致的额外注册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

 

总结消息模式的几大优点

1 解决程序集循环访问的问题

2 程序集解耦,对于少量通信的程序集之间不需要存在引用关系,就可达到互相通讯,亦可减少程序集中的public方法数量。

3 消息以广播的形式进行发送,使得一处发送,多处重复使用。

4 消息集中处理控制更加灵活。

 

转载于:https://www.cnblogs.com/blackvis/p/5782288.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283973.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微服务:注册中心ZooKeeper、Eureka、Consul 、Nacos对比

前言 服务注册中心本质上是为了解耦服务提供者和服务消费者。对于任何一个微服务&#xff0c;原则上都应存在或者支持多个提供者&#xff0c;这是由微服务的分布式属性决定的。更进一步&#xff0c;为了支持弹性扩缩容特性&#xff0c;一个微服务的提供者的数量和分布往往是动…

MyBatis总结七:动态sql和sql片段

开发中&#xff0c;sql拼接很常见&#xff0c;所以说一下动态sql&#xff1a; 1if2chose,when,otherwise3where,set4foreach用法解析(现有一张users表 内有id username age 三个字段)&#xff1a; <!--查询所有用户&#xff0c;传递参数type&#xff0c;如果值为0&#xff0…

iOS - OC Copy 拷贝

前言 copy&#xff1a;需要先实现 NSCopying 协议&#xff0c;创建的是不可变副本。mutableCopy&#xff1a;需要实现 NSMutableCopying 协议&#xff0c;创建的是可变副本。浅拷贝&#xff1a;指针拷贝&#xff0c;源对象和副本指向的是同一个对象。对象的引用计数器 &#xf…

三.选择结构(一)

1.if结构: if(条件){ 代码块 } 2.随机产生数: int randon (int)(Math.random()*10); 3.多重if选择结构: if(条件1){ 代码块1 }else if (条件2){ 代码块2 }else{ 代码块3 } 4.嵌套if选择结构: if(条件1){ if(条件2){ 代码块1 }else{ 代码块2 } }else{ 代码块3 } 转载于:https://…

为了高性能、超大规模的模型训练,这个组合“出道”了

点击上方蓝字关注我们&#xff08;本文阅读时间&#xff1a;3分钟)近年来&#xff0c;在大量数据上训练的基于 transformer 的大规模深度学习模型在多项认知任务中取得了很好的成果&#xff0c;并且被使用到一些新产品和功能背后&#xff0c;进一步增强了人类的能力。在过去五年…

SVN就是这么简单

什么是SVN SVN全称&#xff1a;Subversion&#xff0c;是一个开放源代码的版本控制系统 Svn是一种集中式文件版本管理系统。集中式代码管理的核心是服务器&#xff0c;所有开发者在开始新一天的工作之前必须从服务器获取代码&#xff0c;然后开发&#xff0c;最后解决冲突&…

SpringCloud必会知识点大全

为什么要学习Spring Cloud 在项目开发中随着业务越来越多&#xff0c;导致功能之间耦合性高、开发效率低、系统运行缓慢难以维护、不稳定。微服务 架构可以解决这些问题&#xff0c;而Spring Cloud是微服务架构最流行的实现. 1.微服务 微服务架构是使用一套小服务来开发单个应用…

thinkphp3.22 多项目配置

1.index.php if(version_compare(PHP_VERSION,5.3.0,<)) die(require PHP > 5.3.0 !); // 开启调试模式 建议开发阶段开启 部署阶段注释或者设为false define(APP_DEBUG,true); // 创建 //define(BIND_MODULE,Login); define(erp,true); // 定义应用目录 define(APP_PAT…

30分钟掌握 C#7

1. out 变量&#xff08;out variables&#xff09; 以前我们使用out变量必须在使用前进行声明&#xff0c;C# 7.0 给我们提供了一种更简洁的语法 “使用时进行内联声明” 。如下所示&#xff1a; 1 var input ReadLine(); 2 if (int.TryParse(input, out var result)) 3 …

在 C# 中如何检查参数是否为 null

前言前不久&#xff0c;微软宣布从 C# 11 中移除参数空值检查功能&#xff0c;该功能允许在方法开始执行之前&#xff0c;在参数名称的末尾提供参数空值检查&#xff08;!!操作符&#xff09;。那么&#xff0c;在 C# 中如何检查参数是否为 null 呢&#xff1f;1. null这个可能…

什么是Maven快照(SNAPSHOT)

本文来说下Maven的SNAPSHOT版本有什么作用 文章目录 问题解决 正式版本"abc-1.0"快照版本"abc-1.0-SNAPSHOT"本文小结问题 在使用maven进行依赖管理时&#xff0c;有的版本号后面会带有"-SNAPSHOT"&#xff0c;有什么作用呢&#xff1f; <dep…

带你剖析WebGis的世界奥秘----Geojson数据加载(高级)

前言&#xff1a;前两周我带你们分析了WebGis中关键步骤瓦片加载点击事件&#xff08;具体的看前两篇文章&#xff09;&#xff0c;下面呢&#xff0c;我带大家来看看Geojson的加载及其点击事件 Geojson数据解析 GeoJSON是一种对各种地理数据结构进行编码的格式。GeoJSON对象可…

如果要存ip地址,用什么数据类型比较好

在看高性能MySQL第3版&#xff08;4.1.7节&#xff09;时&#xff0c;作者建议当存储IPv4地址时&#xff0c;应该使用32位的无符号整数&#xff08;UNSIGNED INT&#xff09;来存储IP地址&#xff0c;而不是使用字符串。但是没有给出具体原因。为了搞清楚这个原因&#xff0c;查…

微软 .NET Core 3.1 年底将结束支持,请升级到.NET 6

微软近日宣布&#xff0c;将于 2022 年 12 月 13 日停止为 .NET Core 3.1 提供服务更新、安全修复和技术支持。.NET Core 是一个免费开源的、用于 Windows、Linux 和 macOS 操作系统的软件框架。该项目主要由微软员工通过 .NET 基金会开发&#xff0c;并在 MIT 许可下发布。202…

软件团队的模式选择

软件团队的模式分为&#xff1a;主治医生模式、明星模式、社区模式、业余剧团模式、秘密团队、特工团队、交响乐团模式、爵士乐模式、功能团队模式和官僚模式。 经过小组的讨论&#xff0c;我们决定选用交响乐团模式获得功能团队模式。 交响乐团模式的优点是种类多&#xff0c;…

Angular 2

1. Angular2 官网 https://angular.io/guide/quickstart Node.js 下载 https://nodejs.org/en/ 怎么在vs code中使用angualr2 https://code.visualstudio.com/docs/nodejs/angular-tutorial moment.js:(javacript日期处理库) http://momentjs.cn/ 2. ng2-hightCharts https://…

「Docker入门指北」容器很难理解?带你从头到尾捋一遍

文章目录 1. 初始虚拟化 &#x1f351; 虚拟化概念&#x1f351; 硬件虚拟化2. Docker容器 &#x1f351; Docker技术的诞生&#x1f351; 容器与虚拟化&#x1f351; 性能差别&#x1f351; Docker优势 编排有序高效易迁移快速部署3. 容器生态系统 &#x1f351; 核心技术 容器…

微服务:事务管理

几乎所有的信息管理系统都会涉及到事务&#xff0c;事务的目的是为了保证数据的一致性&#xff0c;这里说的一致性是数据库状态的一致性。说到数据库状态的一致性&#xff0c;相信大家都会想到 ACID &#xff1a;原子性&#xff08;Atomic&#xff09;&#xff1a;在一个事件的…

js - flex布局测试案例:完美居中

<span>I love flex layout!</span><style>body{display:flex;justify-content:center;align-items:center;font-size:3em;color:#00ffff;}</style>![enter image description here][1]<p>与自己为敌&#xff0c;</p><p>与自己为友&a…

操作数据库(对战小游戏)

创建数据库 1 create database duizhan2 go3 use duizhan4 go5 create table duizhan6 (7 Code varchar(20) not null primary key,8 Name varchar(20) not null,9 Sex varchar(20) not null, 10 Blood int, 11 Attack int, 12 Defence int, 13 Mingzhong…