使用EventBus对模块解耦(附实例)
用于模块间解耦,通过发布订阅的方式调用,每个人只负责自己的那部分。
写个小例子,比如现在有三个模块,订单、购物车、优惠券,由不同的人负责开发。
负责订单模块的人现在需要写个生成订单的方法,生成订单的逻辑包括删除购物车项、标记优惠券已使用。
如果直接调用购物车、优惠券两个模块中的方法,耦合性高。
此时可以使用EventBus进行解耦。
public class EventBus { private EventBus() { } private static Object syncObj = new object(); private static EventBus _instance = null; public static EventBus Instance { get { if (_instance == null) { lock (syncObj) { if (_instance == null) { _instance = new EventBus(); } } } return _instance; } } private ConcurrentDictionary<string, List<Action<object[]>>> _dict = new ConcurrentDictionary<string, List<Action<object[]>>>(); private bool ExistEvent(string eventName) { if (_dict.ContainsKey(eventName)) { return true; } return false; } public void InvokeEvent(string eventName,object[] args) { if (!this.ExistEvent(eventName)) { return; } foreach (var eventHandler in this._dict[eventName]) { eventHandler.Invoke(args); } } public void AddEvent(string eventName, Action<object[]> eventHandler) { if (this.ExistEvent(eventName)) { this._dict[eventName].Add(eventHandler); } else { this._dict[eventName] = new List<Action<object[]>> { eventHandler }; } } public void AddEvent(string eventName, List<Action<object[]>> eventHandlerList) { if (this.ExistEvent(eventName)) { this._dict[eventName].AddRange(eventHandlerList); } else { this._dict[eventName] = eventHandlerList; } } public void RemoveEvent(string eventName) { if (this.ExistEvent(eventName)) { this._dict.TryRemove(eventName,out var value); } } public void RemoveEvent(string eventName, Action<object[]> eventHandler) { if (this.ExistEvent(eventName)) { this._dict[eventName].Remove(eventHandler); } } }
public class ShopCartService { /// <summary> /// 删除购物车 /// </summary> /// <param name="shopCartID"></param> public void RemoveShopCart(int orderID) { Console.WriteLine($"已删除订单{orderID}的购物车项"); } } public class CouponService { /// <summary> /// 标记优惠券已使用 /// </summary> public void RecordUsedCoupon(int orderID) { Console.WriteLine($"已将订单{orderID}标记已使用优惠券"); } } public class OrderService { /// <summary> /// 创建订单 /// </summary> public void CreateOrder() { ; Console.WriteLine($"生成订单"); EventBus.Instance.InvokeEvent(EventNames.CREATEORDER_EVENT, new object[] { orderID }); } }
public static class EventNames { public static string CREATEORDER_EVENT = "CreateOrder"; }
---------------------------------------------------------------------------
订阅、发布
static void Main(string[] args) { //订阅 EventBus.Instance.AddEvent(EventNames.CREATEORDER_EVENT, new List<Action<object[]>> { (args)=>{ ].ToString())); }, (args)=>{ ].ToString())); } }); var orderService = new OrderService(); orderService.CreateOrder(); }
使用EventBus对模块解耦(附实例)的更多相关文章
- Java经典设计模式之十一种行为型模式(附实例和详解)
Java经典设计模式共有21中,分为三大类:创建型模式(5种).结构型模式(7种)和行为型模式(11种). 本文主要讲行为型模式,创建型模式和结构型模式可以看博主的另外两篇文章:Java经典设计模式之 ...
- Java设计模式之十一种行为型模式(附实例和详解)
Java经典设计模式共有21中,分为三大类:创建型模式(5种).结构型模式(7种)和行为型模式(11种). 本文主要讲行为型模式,创建型模式和结构型模式可以看博主的另外两篇文章:J设计模式之五大创建型 ...
- (转)Java经典设计模式(3):十一种行为型模式(附实例和详解)
原文出处: 小宝鸽 Java经典设计模式共有21中,分为三大类:创建型模式(5种).结构型模式(7种)和行为型模式(11种). 本文主要讲行为型模式,创建型模式和结构型模式可以看博主的另外两篇文章:J ...
- Linux chmod命令修改文件与文件夹权限的命令附实例
Linux chmod命令修改文件与文件夹权限的命令附实例 作者:佚名 字体:[增加 减小] 来源:互联网 时间:05-01 20:46:07我要评论 在linux中要修改一个文件夹或文件的权限我们需 ...
- Java经典设计模式之七大结构型模式(附实例和详解)
博主在大三的时候有上过设计模式这一门课,但是当时很多都基本没有听懂,重点是也没有细听,因为觉得没什么卵用,硬是要搞那么复杂干嘛.因此设计模式建议工作半年以上的猿友阅读起来才会理解的比较深刻.当然,你没 ...
- Java设计模式之七大结构型模式(附实例和详解)
博主在大三的时候有上过设计模式这一门课,但是当时很多都基本没有听懂,重点是也没有细听,因为觉得没什么卵用,硬是要搞那么复杂干嘛.因此设计模式建议工作半年以上的猿友阅读起来才会理解的比较深刻.当然,你没 ...
- (转)Java经典设计模式(2):七大结构型模式(附实例和详解)
原文出处: 小宝鸽 总体来说设计模式分为三大类:创建型模式.结构型模式和行为型模式. 博主的上一篇文章已经提到过创建型模式,此外该文章还有设计模式概况和设计模式的六大原则.设计模式的六大原则是设计模式 ...
- web自动化测试-模块驱动测试实例和数据驱动测试实例
一.模块驱动测试实例 把登录和退出统一封装在login类中,若把login类单独放在一个文件中,就可以给任一测试脚本调用,这里就跟测试脚本放一起 from selenium import webdri ...
- Python命令行参数解析模块getopt使用实例
Python命令行参数解析模块getopt使用实例 这篇文章主要介绍了Python命令行参数解析模块getopt使用实例,本文讲解了使用语法格式.短选项参数实例.长选项参数实例等内容,需要的朋友可以参 ...
随机推荐
- Qt 调试信息、打印信息、输出到文本
void debug_msg(QVariant msg) { ; QFile file("debug_msg.txt"); ) { i = ; file.open(QFile::W ...
- JSP还有必要学吗?这篇文章告诉你
阅读本文大概需要 12.4 分钟. 来源:http://suo.im/4wqRi7 作者:杨明翰 前戏 前后端分离已成为互联网项目开发的业界标准使用方式,通过nginx+tomcat的方式(也可以 ...
- qps.sh
mysql -p'' -Bse'show global status like "com_%";' > qps.new while true do sleep 0.5 mv ...
- 【网络知识之五】TCP
TCP协议:传输控制协议. 一.TCP保证可靠性的机制1.校验和 TCP报头有16位检验和: 由发送端填充, 检验形式有CRC校验等. 如果接收端校验不通过, 则认为数据有问题. 此处的校验和不光包含 ...
- Vue.js 源码分析(十一) 基础篇 过滤器 filters属性详解
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化.过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持).过滤器应该被添加在 JavaScrip ...
- CentOS安装vsftpd FTP后修改默认21端口方法
第一步:修改配置文件 vi /etc/vsftpd/vsftpd.conf 首先需要在vsftpd配置文件中添加: listen_port=1802pasv_enable=YESpasv_min_po ...
- 添加wcf服务引用,无法签出当前文件
写了一些wcf服务接口,使用控制台可以正常启动服务,想要测试一下,新建项目添加服务引用,提示:“无法签出当前文件.该文件可能为只读或已锁定,或者您需要手动签出它.” 在网上找了找,有说可能是因为源代码 ...
- webapi 返回类型
参考 大神;https://www.cnblogs.com/landeanfen/p/5501487.html
- MySQL难点语法——子查询
本篇主要通过练习来讲解子查询的知识,进入正题之前,先熟悉数据表,表格的数据可以先不用管,主要是熟悉表格的字段名 这里子查询分为三个部分: 1.where条件子查询 这个子查询和普通的查询没什么区别,主 ...
- sql脚本来获取数据库中的所有表结构了
sql脚本来获取数据库中的所有表结构了,代码如下: use AdventureWorks2008 go SELECT (case when a.colorder=1 then d.name else ...