上一讲主要说了领域事件和领域总线,这并不是一个很容易理解的文章,所以本讲实例篇主要是为了补充上一讲的理论知识,本讲实例关注的是实际中的订单处理模块,我们知道,订单处理是电子商务的核心,往往在这里面,会有很多逻辑,在开发时,给我们带来了不少的难度,如何更好的分离关注点,是本讲的主题;本讲主要是修改订单状态后,为用户发通知为例,来以此更好的说一下领域事件在实际中的作用。

前言 领域事件使用的设计模式是发布/订阅模式,或者叫观察者模式。

一 订单的几种状态,在订单进入到其中一些状态时,需要通知用户

  public enum OrderStatus{/// <summary>/// 表示销售订单的已创建状态 - 表明销售订单已被创建(未用)。/// </summary>[Description("用户下单")]Created = 0,/// <summary>/// 订单被用户取消/// </summary>[Description("取消订单")]Canceled,/// <summary>/// 表示销售订单的已付款状态 - 表明客户已向销售订单付款。/// </summary>[Description("用户付款")]Paid,/// <summary>/// 表示销售订单的已发货状态。/// </summary>[Description("已经发货")]Dispatched,/// <summary>/// 订单已经完成/// </summary>[Description("订单完成")]Finished,}

二 为需要通知的状态,创建领域事件数据源(原来在.net事件里,它一般是EventArgs对象)

    /// <summary>/// 订单已经确认事件源/// </summary>public class Order_Confirm_Event : Project.Events.EventBase{public int OrderId { get; set; }public string UserName { get; set; }}

    /// <summary>/// 订单已经付款事件缘/// </summary>public class Order_Paid_Event : Project.Events.EventBase{public int OrderId { get; set; }public string UserName { get; set; }public decimal TotalPrice { get; set; }}

    /// <summary>/// 订单已经发货事件源/// </summary>public class Order_Dispatch_Event : Project.Events.EventBase{public int OrderId { get; set; }public string UserName { get; set; }}

三 为这些事件源添加事件处理方式

我们一般理解为“行为”,一种事件源可以有多种事件行为,如一个订单付款事件源,它可以同时有电子邮件行为和短信行为;反之,一个事件处理方式也可以对应多个事件源,如一个电子邮件行为,它可以同时对应订单付款

和订单发货等事件源,所以,领域事件在项目中是非常灵活的。

    /// <summary>/// 发Email的事件处理方式/// 调用方法:EventBus.Instance.Subscribe<User_Depts_Event>(new SendEmailEventHandler())///      EventBus.Instance.Subscribe<User_Roles_Event>(new SendEmailEventHandler())/// </summary>public class SendEmail_EventHandler :IEventHandler<Order_Confirm_Event>,IEventHandler<Order_Dispatch_Event>,IEventHandler<Order_Paid_Event>{static string prefix = "本消息来自电子邮件";#region IEventHandler<Order_Confirm_Event> 成员public void Handle(Order_Confirm_Event evt){Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客户{0},你的订单已经确认,订单号{1},请尽快付款!({2})[{3}]", evt.UserName, evt.OrderId, evt.EventDate, prefix));}#endregion#region IEventHandler<Order_Dispatch_Event> 成员public void Handle(Order_Dispatch_Event evt){Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客户{0},你的订单已经发货,订单号{1},请注意查收!({2})[{3}]", evt.UserName, evt.OrderId, evt.EventDate, prefix));}#endregion#region IEventHandler<Order_Paid_Event> 成员public void Handle(Order_Paid_Event evt){Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客户{0},你的订单已经成功付款,订单号{1},付款金额为{2}元,我们会尽快安排发货!({3})[{4}]", evt.UserName, evt.OrderId, evt.TotalPrice, evt.EventDate, prefix));}#endregion}

    /// <summary>/// 发短信的事件处理方式/// </summary>public class SendSMS_EventHandler :IEventHandler<Order_Confirm_Event>,IEventHandler<Order_Dispatch_Event>,IEventHandler<Order_Paid_Event>{static string prefix = "本消息来自短信";#region IEventHandler<Order_Confirm_Event> 成员public void Handle(Order_Confirm_Event evt){Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客户{0},你的订单已经确认,订单号{1},请尽快付款!({2})[{3}]", evt.UserName, evt.OrderId, evt.EventDate, prefix));}#endregion#region IEventHandler<Order_Dispatch_Event> 成员public void Handle(Order_Dispatch_Event evt){Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客户{0},你的订单已经发货,订单号{1},请注意查收!({2})[{3}]", evt.UserName, evt.OrderId, evt.EventDate, prefix));}#endregion#region IEventHandler<Order_Paid_Event> 成员public void Handle(Order_Paid_Event evt){Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客户{0},你的订单已经成功付款,订单号{1},付款金额为{2}元,我们会尽快安排发货!({3})[{4}]", evt.UserName, evt.OrderId, evt.TotalPrice, evt.EventDate, prefix));}#endregion}

四 订阅领域事件

我们需要有一个入口来订阅领域事件,如订阅订单确认事件,订单付款事件等,简单的做法是在global里统一注册,而标准合理的作法,我觉得应该在订单controller的静态构造方法里去注册它,因为只有用户操作订单相关模块时,才可能触

发订单这些事件!

     /// <summary>/// 类的构造方法,处理与具体实例无法的东西/// </summary>static OrderController(){#region 订阅相关领域事件#region 订阅发email处理方式EventBus.Instance.Subscribe<Order_Confirm_Event>(new SendEmail_EventHandler());EventBus.Instance.Subscribe<Order_Dispatch_Event>(new SendEmail_EventHandler());EventBus.Instance.Subscribe<Order_Paid_Event>(new SendEmail_EventHandler());#endregion#region 订阅发短信的处理方式EventBus.Instance.Subscribe<Order_Confirm_Event>(new SendSMS_EventHandler());EventBus.Instance.Subscribe<Order_Dispatch_Event>(new SendSMS_EventHandler());EventBus.Instance.Subscribe<Order_Paid_Event>(new SendSMS_EventHandler());#endregion#endregion}

我们看到了,每种订单事件源都被注册了电子邮件和短信两种事件处理方式,这在对应的事件被触发(发布,publish)之后,它们会被执行。

六 触发具体事件

具体的事件在具体的方法里,独立的去触发,一般它会在业务逻辑层完成

     /// <summary>/// 用户下单:create/// </summary>/// <param name="entity"></param>public void DoOrder(Order_Info entity){entity.OrderStatus = (int)OrderStatus.Created;_orderRepository.Insert(entity);entity.Order_Detail.ToList().ForEach(j => j.OrderId = entity.Id);_orderDetailRepository.Insert(entity.Order_Detail);EventBus.Instance.Publish(new Order_Confirm_Event { OrderId = entity.Id, UserName = entity.UserName });}/// <summary>/// 订单付款:paid/// </summary>/// <param name="entity"></param>public void PaidOrder(Order_Info entity){entity.OrderStatus = (int)OrderStatus.Paid;_orderRepository.Update(entity);EventBus.Instance.Publish(new Order_Paid_Event { OrderId = entity.Id, TotalPrice = entity.TotalPrice, UserName = entity.UserName });}/// <summary>/// 订单发货:dispatch/// </summary>/// <param name="entity"></param>public void DispatchOrder(Order_Info entity){entity.OrderStatus = (int)OrderStatus.Dispatched;_orderRepository.Update(entity);EventBus.Instance.Publish(new Order_Dispatch_Event { OrderId = entity.Id, UserName = entity.UserName });}

八 最后,我们看一下处理处理页面和结果的截图

生成的日志

生成的日志内容,类似于用户上到的电子邮件或者短信的内容

怎么样,看完这个例子相信您对领域事件有了更清晰的认识了吧,呵呵!

本文转自博客园张占岭(仓储大叔)的博客,原文链接:DDD~领域事件应用篇(订单处理变得更清晰),如需转载请自行联系原博主。

DDD~领域事件应用篇(订单处理变得更清晰)相关推荐

  1. DDD~领域事件与事件总线

    DDD~领域事件与事件总线 回到目录 谈谈它 终于有些眉目了,搜刮了很多牛人的资料,英文的,中文的,民国文的,终于小有成就了,同时也做了个DEMO,领域事件这东西好,但需要你明白它之后才会说好,而对于 ...

  2. DDD~领域事件中使用分布式事务

    对于一个聚合来说,它可能会被附加很多事件,这里我们叫它领域事务,因为一个聚会我们可以把它理解成一个领域,一个业务.对于领域事件不清楚的同学可以看看我的这篇文章<DDD~领域事件与事件总线> ...

  3. java ddd 领域事件_Cribbb基于DDD/Domain Event领域事件的开源PHP通知系统

    Cribbb是一个使用DDD聚合根和领域事件Domain Events概念开发的PHP开源通知框架:cribbb/cribbb · GitHub 几乎所有Web应用都有一个通知提醒系统,这些通知系统都 ...

  4. 如何一步一步用DDD设计一个电商网站(十三)—— 领域事件扩展

    本系列所有文章 如何一步一步用DDD设计一个电商网站(一)-- 先理解核心概念 如何一步一步用DDD设计一个电商网站(二)-- 项目架构 如何一步一步用DDD设计一个电商网站(三)-- 初涉核心域 如 ...

  5. DDD理论学习系列(9)-- 领域事件

    1. 引言 A domain event is a full-fledged part of the domain model, a representation of something that ...

  6. Lind.DDD.Events领域事件介绍

    闲话多说 领域事件大叔感觉是最不好讲的一篇文章,所以拖欠了很久,但最终还是在2015年年前(阴历)把这个知识点讲一下,事件这个东西早在C#1.0时代就有了,那时学起来也是一个费劲,什么是委托,哪个是事 ...

  7. DDD领域驱动设计三、用事件风暴构建领域模型

    文章目录 一.准备事件风暴 1.参与人员 2.环境条件 二.确定产品愿景 参与角色: 三.业务场景分析 1.参与角色: 2.实例 四.领域建模 1.参与角色: 2.思考 3.实例 五.微服务拆分与设计 ...

  8. DDD(六)【领域事件与事件总线】

    谈谈它 终于有些眉目了,搜刮了很多牛人的资料,英文的,中文的,民国文的,终于小有成就了,同时也做了个DEMO,领域事件这东西好,但需要你明白它之后才会说好,而对于明白领域事件这件事来说,它的门槛有点高 ...

  9. ddd领域驱动设计_领域驱动设计(DDD)理论启示

    过去几年通天塔一直处于快速的业务能力建设和架构完善的阶段,以应对不断增长的业务需求和容量.高可用等技术需求,现在通天塔平台已经能满足集团主站的大部分活动.频道搭建和运营能力,主流程的新需求越来越少,个 ...

  10. 一文带你学习DDD,基础入门篇

    系统讲解DDD的基础概念,结合具体的Demo讲解DDD落地场景. 往期精选(欢迎转发~~) 如何看待程序员35岁职业危机? Java全套学习资料(14W字),耗时半年整理 我肝了三个月,为你写出了GO ...

最新文章

  1. 孩子、老人与海豚,如何用 AI 伴他们走出孤独
  2. jenkins 添加 证书凭证Credentials
  3. matlab中的single是什么类型_MATLAB 中cell数据类型的使用方法
  4. 《STL源码剖析》学习--六大组件
  5. 在linux中安装软件会出的问题,linux中安装程序出现的问题
  6. 细说新一代HTML5/JavaScript的UI控件wijmo5 的新架构
  7. 阅读下面程序,请回答如下问题:
  8. 在Apache中利用ServerAlias设置虚拟主机接收多个域名和设置域名泛解析
  9. Redis数据库15点介绍
  10. GTD时间管理(3)---梳理总结
  11. angular1的复选框指令--checklistModel
  12. 基于安卓Android银行排队叫号系统设计与实现
  13. 如何配置ASP运行环境
  14. Live2D 博客页面添加板娘
  15. 关于docker容器中,外网访问阿里云服务器中tomcat,报404错误的解决方法
  16. html span向上对齐,css也能让span靠左布局
  17. 《掌控》及其自我掌控
  18. HTTPS能否避免流量劫持?
  19. 十三不香了?iPhone 14配置完全曝光:外观性能全面升级
  20. 与君共勉之--施一公教授的演讲

热门文章

  1. Linux安装IDA神器
  2. WPF:Hyperlink如何绑定数据
  3. C# 时时监听目录文件改动
  4. python实训day7
  5. UML类图各符号含义
  6. 程序员编程艺术第十六~第二十章:全排列,跳台阶,奇偶调序等问题
  7. Winform 分页用户自定义控件( ML.Pager.WinControl)
  8. maven3常用命令、java项目搭建、web项目搭建详细图解
  9. python 库文件版本收集及安装
  10. 「日常训练」Queue(Codeforces Round 303 Div.2 D)