事件驱动上
前言
今天講一下事件驅動,這個不是領域驅動設計里的事件源(Event Source), 這個以后再講,今天主要講一下如何用事件來解耦,主要的原因是我們有個項目有個功能我覺得用事件的方式比較好,正好寫篇博客,就不用專門給他們講了。
解耦
說到解耦,我們很熟悉分層設計,比如上層依賴于抽象,不依賴于具體的實現。比如一個類使用另一個類,我們使用接口而不直接使用實現類。
public EquipmentService(IEmailService emailService, IEquipmentRepository equipmentRepository){_emailService = emailService;_equipmentRepository = equipmentRepository;}為何用事件?
SRP (單一職責)
比如我們一個會議室預定系統,我們的一個設備壞了。我們需要通知預定這個會議室的所有人。于是我們需要發郵件。
偽代碼如下
public class EquipmentService {private readonly IEmailService _emailService; private readonly IEquipmentRepository _equipmentRepository; public EquipmentService(IEmailService emailService, IEquipmentRepository equipmentRepository) { _emailService = emailService; _equipmentRepository = equipmentRepository; } public void SetEquipmentBroken(string Id) { var equipment = _equipmentRepository.GetById(Id); equipment.DeActive(); _emailService.SendEmail(); } }但是,問題來了,如果后來我們要說,如果設備壞了,我們要更改可用庫存的數量,這時候我們是不是要在這里修改代碼而引入IInventoryService? 后來如果經理說設備壞了你們盡然不告訴我,你們要鬧哪樣?這個時候我們是不是要修改代碼引入ISMSService.Info(Manager)? 即使我們不考慮OCP原則,不考慮單一職責,我們程序員也會哭,我就DeActive一個設備,你要我做這么多事,我哪里清楚所有的功能?我就罵過程序員,你做這個功能呢為什么沒考慮全!!!漏掉了這么重要的功能。
而問題,程序員從來沒考慮全過,因此我就想辦法如何解決這個程序員不仔細的問題。
事件驅動
因為我熟悉iOS的開發,我就想到了iOS的Notification Center. 那我我DeActive一個設備,我就只DeActive這個設備,很SRP是不是? 但是別的地方如何拿到通知? 于是事件就自然的付出水面了。如果設備被DeActive了,程序就只需要喊一聲,老子把設備DeActive了,你們要鬧哪樣你們自己看著辦,代碼如下。
public void SetEquipmentBroken(string Id) { var equipment = _equipmentRepository.GetById(Id); equipment.DeActive(); EventBus.Publish(new EquipmentDeActivedEvent {Id = equipment.Id}); }這樣,通知會議室預定者的模塊去通知,給老板發短信的模塊就通知老板就OK了。
總結
這里我們先將事件驅動,下一篇展示如何實現同步的事件,以后轉換為異步那也很容易,讓多個接受者處理這個事件,接受者可以是動態的哦,以后老板娘也想知道的話,代碼也不用改的親,好,我先去寫實現代碼去!
- 作者: 王德水
- 出處:http://deshui.wang
總結