使用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使用实例,本文讲解了使用语法格式.短选项参数实例.长选项参数实例等内容,需要的朋友可以参 ...
随机推荐
- android 自定义gridview(导航)
最近又重新做回安卓,做了个小项目.下绝心使用android studio,通过这一回实战,终于用上了.综合了前人的经验,搞了个自己满意的导航界面,用的是gridview. 代码: package co ...
- Idea必知必会
声明:此文章根据后续用的越来越多,将会不断补充,之所以以链接的形式,是因为不想在这种使用层面上重复造轮子,写很多重复文章,后续我打算写一些更深入的文章. idea常用操作: idea如何Debug调试 ...
- 在Azure DevOps Server(TFS)上集成Python环境,实现持续集成和发布
Python和Azure DevOps Server Python是一种计算机程序设计语言.是一种动态的.面向对象的脚本语言,最初主要为系统运维人员编写自动化脚本,在实际应用中,Python已经在前端 ...
- pyqt 调用QT设计师创建的对话框
一.实验环境 1.Windows7x64_SP1 2.anaconda2.5.0 + python2.7(anaconda集成,不需单独安装) 3.pyinstaller3.0 二.实验步骤 2.1 ...
- 社招C++后台面试-拿到offer
社招C++后台面试-拿到offer 之前在一家小公司上班,主要是做C语言的嵌入式软件开发,涉及过一点点C++.工作大概三年,然后去试试大公司,这个面试题是我拿到offer后4个月才拖拖拉拉的开始写,题 ...
- python3 字符和数字(ASC码)转换
print(ord('b')) print(ord('B')) print(chr(98)) print(chr(66)) 结果:98 66 b B 也可以数字转ASC码,原理一样,如下(结果就不输出 ...
- 面向对象之isinstance与issubclass(python内置方法)
isinstanceissubclass TOC isinstance 判断一个对象是否是另外一个类的实例,返回布尔值. 是:True 否:False class Foo: pass class Bo ...
- DirectX:Vector
Tag DirectX下的博客主要用于记录DirectX的学习过程,主要参考<DirectX 12 3D 游戏实战开发>. Vector in DirectX Shader的编写离不开数学 ...
- sql server报【从varchar数据类型到datetime数据类型的转换产生一个超出范围的值】错误的解决办法
产生这个错误的原因是在使用convert函数将给定的日期字符串转换为日期类型的时候,因为datetime这个数据类型有时间数值的范围限定,当超出时间范围时就抛出这个错误. 如果类型是[datetime ...
- Android开发中网络代理设置实用总结
一.背景 进行Android项目开发时,跟网络代理基本上天天都在打交道.通常情况下,至少有三个场景中经常用到网络代理: 1,经常通过Chrome访问Google等国外的技术网站,如通过SS工具等: 2 ...