一 背景
在上面的一篇文章中我們介紹了一個完整地基于消息釋出和訂閱的模型,這篇文章我将介紹一種簡單的基于消息的釋出和訂閱模型,在這個模型中我們将通過建構一個Publisher類來完成對特定的事件和事件訂閱進行封裝,這個是一個更加輕量級别的方式,使用這個的主要目的是降低類之間彼此的耦合程度,進而友善代碼的擴充和通路,最終使代碼結構更加合理。
我們首先來看看具體的Publisher類的構成,後面我們将會對這個類做一個詳細的講解和分析。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Pangea.Common.Utility
{
/// <summary>
/// Publisher/Subscriber pattern
/// This infrastructure works as an instance.
/// </summary>
public sealed class Publisher<EventType> where EventType : IComparable
{
private static readonly object _locker = new object();
private static readonly Dictionary<EventType, List<Action<object, object, object, object>>> _eventTypeList = new Dictionary<EventType, List<Action<object, object, object, object>>>();
public static void Attach(EventType key, Action<object, object, object, object> act)
{
lock (_locker)
{
if (!_eventTypeList.ContainsKey(key))
_eventTypeList.Add(key, new List<Action<object, object, object, object>>());
if (!_eventTypeList[key].Contains(act))
_eventTypeList[key].Add(act);
}
}
public static void Detach(EventType key)
{
lock (_locker)
{
if (_eventTypeList.ContainsKey(key))
{
_eventTypeList[key].Clear();
}
}
}
public static void Detach(EventType key, Action<object, object, object, object> act)
{
lock (_locker)
{
if (_eventTypeList.ContainsKey(key) && _eventTypeList[key].Contains(act))
{
_eventTypeList[key].Remove(act);
}
}
}
public static void Notify(EventType key, object p1, object p2, object p3, object p4)
{
lock (_locker)
{
if (_eventTypeList.ContainsKey(key))
{
foreach (var act in _eventTypeList[key])
{
act.Invoke(p1, p2, p3, p4);
}
}
}
}
public static void Notify(EventType key, object p1, object p2, object p3)
{
Notify(key, p1, p2, p3, null);
}
public static void Notify(EventType key, object p1, object p2)
{
Notify(key, p1, p2, null, null);
}
public static void Notify(EventType key, object p1)
{
Notify(key, p1, null, null, null);
}
public static void Notify(EventType key)
{
Notify(key, null, null, null, null);
}
}
}
二 完成分析
在上面的Publisher類中,我們使用了一個EventType類型的泛型參數,這個參數由我們自己來進行定義,一般定義為枚舉類型用于辨別我們唯一的事件類型,定義好了泛型參數後我們定義了一個_eventTypeList用于定義具體的EventType和對應的處理方法并且将這個放到一個靜态的Dictionary中,當然我們在代碼中一個事件可以對應多個處理的Action,但是在一般情況下一個事件隻有一個對應的處理函數,這裡也不排除一個事件對應多個事件的處理函數,另外這裡我們預設定義了四個object類型的參數,用于向處理函數進行參數的傳遞,另外我們的方法都是靜态的方法并且在訂閱的過程中加了鎖進而保證了多線程的環境中保證線程的安全性。
三 使用過程
在具體的使用過程中主要包括三個重要的步驟:1 定義事件類型。2 消息接收方訂閱事件處理(一般在構造函數中調用Attach方法建立時間的唯一訂閱)。3 事件釋出方釋出事件(事件的發送方觸發時間并傳遞參數,調用Notify方式觸發事件),完成以上三個步驟就完成了整個基于消息的釋出訂閱的簡單處理,這個Publisher類在處理一般的事件方法中都能夠順利實作,最重要的是事件本身簡單易于了解而且能最大程度上降低子產品間的耦合,是以在使用的時候還是非常友善的。