使用策略模式實現(xiàn)報警服務(wù)示例詳解(短信報警)
著重說一下策略模式。首先需要定義一個接口,該接口用來統(tǒng)一報警方法,代碼如下:
/// <summary>
/// 報警接口,統(tǒng)一各種報警方式發(fā)出報警的方法
/// </summary>
public interface IAlarm
{
void Alarm(Message message);
}
大家伙看到Message會不會比較疑惑呢,別著急,Message就是我自己定義的一個報警的模型,比如報警標題,收件人(報警報給誰呢),報警方式(郵件、客戶端等)等。
定義好接口之后,我們就要實現(xiàn)這個接口,實現(xiàn)這個接口的就是各種報警方式的類,比如EmailAlarm.cs和ClientAlarm.cs,下面是郵件報警的具體實現(xiàn),EmailAlarm.cs的代碼(需要實現(xiàn)IAlarm接口的Alarm方法):
/// <summary>
/// 郵件報警
/// </summary>
public class EmailAlarm : IAlarm
{
/// <summary>
/// 發(fā)送郵件實現(xiàn)了IAlarm接口的Alarm()方法
/// </summary>
/// <param name="messag"></param>
public void Alarm(Message message)
{
// 此處為郵件報警的具體實現(xiàn)代碼
}
}
下面是客戶端報警的具體實現(xiàn),ClientAlarm.cs(同樣需要實現(xiàn)IAlarm接口的Alarm()方法)
/// <summary>
/// 客戶端報警
/// </summary>
public class ClientAlarm : IAlarm
{
/// <summary>
/// 實現(xiàn)接口IAlarm接口的Alarm()方法
/// </summary>
public void Alarm(Message message)
{
//此處為客戶端實現(xiàn)報警的具體代碼
}
}
好了,基礎(chǔ)工作都做完,接下來我們面臨的問題是我們該如何調(diào)用不同的報警實現(xiàn)呢?當然,在我們的報警模型Message中有報警方式這一字段,我們需要根據(jù)報警方式這個字段來發(fā)不同的報警。這個還不簡單,我們根據(jù)不同的報警方式生成不同的對象,然后各自調(diào)用Alarm()方法就ok。當然,這是一種解決方法,但是這是最好的解決方法嗎?of course not!聽說過反射嗎,小伙伴們?接下來,我將介紹如何利用反射來調(diào)用不同的報警方式:
/// <summary>
/// 統(tǒng)一發(fā)出各種報警的類,將所有調(diào)用報警的操作封裝在這個類中,主程序需要報警時,直接調(diào)用這個類就可以,無需知道其他任何類的存在
/// </summary>
public class AlarmContext
{
private static readonly IDictionary<AlarmWay,IAlarm> _alarmsDic = new Dictionary<AlarmWay, IAlarm>();
static AlarmContext()
{
foreach (AlarmWay way in Enum.GetValues(typeof (AlarmWay)))
{
try
{
Assembly asm = Assembly.GetExecutingAssembly();
Object obj = asm.CreateInstance("MOPlatform.Alert." + way + "Alarm", true);
IAlarm alarm = obj as IAlarm;
_alarmsDic[way] = alarm;
}
catch (Exception ex)
{
Logger.Error("通過反射構(gòu)造報警實例時出現(xiàn)異常:" + ex);
}
}
}
/// <summary>
/// 通過發(fā)射,調(diào)用不同的報警方式
/// </summary>
public void HandleMessage(Message message)
{
foreach (AlarmWay way in Enum.GetValues(typeof(AlarmWay)))
{
//遍歷所有的報警方式,每一種報警方式與message.AlarmWays進行按位與運算,如果運算結(jié)果仍然為當前遍歷的報警方式,則說明Message中包含這種報警方式
if ((message.AlramWays & way) == way)
{
try
{
_alarmsDic[way].Alarm(message);
}
catch (Exception ex)
{
//記錄錯誤日志
}
}
}
}
}
看到AlarmWay是不是又混亂了呢?千萬別亂,AlarmWay就是我定義的一個枚舉類型,里面包含了各種報警方式,具體的代碼我會在文章的最后貼出。我們現(xiàn)在還是著重討論上面的代碼,親愛的小伙伴們,看到上面的靜態(tài)構(gòu)造函數(shù)了嗎?知道為什么要這樣寫嗎?我們在靜態(tài)構(gòu)造函數(shù)中利用反射將枚舉中所有的報警對象保存在IDictionary中,具體的保存如_alarmsDic['Email'] = (IAlarm)EmailAlarm。這樣做的好處小伙伴們自己琢磨吧,嘻嘻。
最后就是我們在主程序中調(diào)用AlarmContext來發(fā)出報警,具體的調(diào)用代碼如下:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("報警服務(wù)已啟動。。。");
//message應(yīng)該是從別的程序傳遞過來的需要報警的消息,比如在Redis隊列中獲取message,具體怎么獲取根據(jù)需求而定。在這里為了方便,我新生成一個對象,其實不應(yīng)該這樣做
Message message = new Message();
AlarmContext context = new AlarmContext();
context.HandleMessage(message);
}
}
OK,到此為止,利用策略模式設(shè)計的報警服務(wù)就介紹完畢啦。這篇文章的主要知識點我認為有兩個,一個是策略模式,另一個就是利用反射。希望廣大的小伙伴們提出寶貴的意見,最后,貼出枚舉AlarmWay的代碼:
/// <summary>
/// 報警方式
/// </summary>
public enum AlarmWay
{
Email = 1,
Client = 2,
ShortMessage = 4
}
順便,小伙伴們思考一下為什么ShortMessage的值是4而不是3呢?
相關(guān)文章
C# CultureInfo之常用InvariantCulture案例詳解
這篇文章主要介紹了C# CultureInfo之常用InvariantCulture案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-08-08c#基于WinForm的Socket實現(xiàn)簡單的聊天室 IM
這篇文章主要介紹了c#基于WinForm的Socket實現(xiàn)簡單的聊天室 IM的步驟,幫助大家更好的理解和學習使用c#,感興趣的朋友可以了解下2021-05-05WPF利用TextBlock實現(xiàn)查找結(jié)果高亮顯示效果
在應(yīng)用開發(fā)過程中,經(jīng)常遇到這樣的需求:通過關(guān)鍵字查找數(shù)據(jù),把帶有關(guān)鍵字的數(shù)據(jù)顯示出來,同時在結(jié)果中高亮顯示關(guān)鍵字,所以本文就來和大家介紹一下如何利用TextBlock實現(xiàn)查找結(jié)果高亮顯示效果吧2023-08-08C#實現(xiàn)Menu和ContextMenu自定義風格及contextMenu自定義
ContextMenu 類表示當用戶在控件或窗體的特定區(qū)域上單擊鼠標右鍵時會顯示的快捷菜單,要想實現(xiàn)自定義的Menu和ContextMenu效果,大家可以通過派生ProfessionalColorTable類,下面小編把實現(xiàn)Menu和ContextMenu自定義風格及ContextMenu自定義給大家整理一下2015-08-08C#創(chuàng)建windows系統(tǒng)用戶的方法
這篇文章主要介紹了C#創(chuàng)建windows系統(tǒng)用戶的方法,涉及C#操作用戶名、密碼、顯示名稱、描述、是否強制修改密碼、密碼是否過期等技巧,非常具有實用價值,需要的朋友可以參考下2015-04-04C#?計算DataTime的4種時間差的方法(相差天數(shù)、相差小時、相差分鐘、相差秒)
這篇文章主要介紹了C#?計算DataTime的4種時間差(相差天數(shù)、相差小時、相差分鐘、相差秒),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-05-05