錯誤日誌之觀察者模式

  星期一

  情景

  早晨,項目組長來到身邊,“有人反映咱們的項目有Bug” “什麼Bug?” “不知道,你添加一個日誌模塊自己看記錄去。” ”...“

  分析

  在MVC全局過濾器中自己添加有異常過濾器。

  Global.asax

  

View Code


  FilterConfig.cs

  

View Code


  開工

  整理思路:發生錯誤時要執行自己需要的代碼,只需要繼承IExceptionFilter,重寫OnException方法,然後把自己的過濾器註冊到全局即可。

  創建過濾器,MyExceptionFilter類

  

複製代碼


  1 //因爲微軟已經提供了一個HandleErrorAttribute類(它其實也是繼承了IExceptionFilter),所以我們只需繼承它即可

  2 public class MyExceptionFilter: HandleErrorAttribute

  3 {

  4 //重寫OnException方法

  5 public override void OnException(ExceptionContext filterContext)

  6 {

  7 base.OnException(filterContext);

  8

  9 //把錯誤寫到日誌文件裏面去

  10 //思考:如果同時來了多個錯誤,一起向文件中寫內容,就會發生同時訪問同一個文件問題。你會怎麼解決?

  11 //提示:鎖、隊列

  12

  13 //LogHelper類用來把錯誤寫到日誌裏面去

  14 LogHelper.Write(filterContext.Exception.ToString());

  15

  16 }

  17 }

  

複製代碼


  LogHelper類,用來把錯誤寫到日誌裏面去

  

View Code


  把自己的過濾器註冊到全局

  

View Code


  自定義錯誤測試

  

View Code


  


  OK,大功告成,以後就可以根據日誌來找錯誤了。

  星期二

  情景

  早晨,項目組長又來到小身邊,”昨天我用了你的錯誤日誌功能,還不錯,但是你將日誌寫在文件中整理不是太方便,還存在共享衝突問題,你改下寫到數據庫中“ ”...“

  分析

  查看昨天寫的代碼

  


  發現此處是一個變化點,有可能寫到文件中,有可能寫到數據庫中,有可能......

  不就是寫到不同的地方麼,簡單,多態就能搞定了。

  開工

  依賴於抽象,而不依賴於具體

  創建IWriteLog接口

  

View Code


  創建WriteLogToText類實現接口,用來寫入文本

  

View Code


  創建WriteLogToSqlServer類實現接口,用來寫入數據庫

  

View Code


  對變化點進行修改

  

複製代碼


  1 ThreadPool.QueueUserWorkItem(o=> {

  2 lock (ExceptionStringQueue) {

  3 string exceptionString = ExceptionStringQueue.Dequeue();

  4 //依賴接口

  5 IWriteLog writeLog = new WriteLogToSqlServer();

  6 //IWriteLog writeLog = new WriteLogToText();

  7 //把錯誤信息寫到相應的地方

  8 writeLog.WriteLog(exceptionString);

  9

  10 }

  11 });

  

複製代碼


  OK,大功告成,又可以去美滋滋了...

  星期三

  情景

  早晨,項目組長再一次來到小身邊,”經過我的思考,我覺得把錯誤信息同時寫到文本和數據庫中比較好“ ”爲什麼?“ “需求” “...”

  分析

  


  錯誤信息有可能要寫到不同的地方,而且不知道有多少地方,說不定明天又加了一個Redis、後天再加一個....

  這時候我們可以考慮創建一個集合來保存都需要寫到那些地方去。(這裏插一句:設計模式只是一種思想,實現方式肯定是不唯一的,但是思想是精髓,不能說這個代碼是這個模式,換一種方式實現就不是這個模式了。)

  然後依次寫入即可。

  開工

  對LogHelper進行修改鄭州不孕不育醫院:http://jbk.39.net/yiyuanzaixian/zztjyy/鄭州不孕不育醫院哪家好:http://jbk.39.net/yiyuanzaixian/zztjyy/鄭州不孕不育醫院排行:http://jbk.39.net/yiyuanzaixian/zztjyy/

  

複製代碼


  1 public class LogHelper

  2 {

  3 //添加一個靜態的異常信息隊列,只要出現異常就寫到隊列中。

  4 public static QueueExceptionStringQueue = new Queue();

  5

  6 //定義一個集合來存放所有的 觀察者,

  7 public static IListwriteLogList = new List();

  8

  9 //第一次用到該類型時會執行靜態構造函數,只被執行一次

  10 static LogHelper() {

  11

  12 //觀察(訂閱)

  13 writeLogList.Add(new WriteLogToSqlServer());

  14 writeLogList.Add(new WriteLogToText());

  15

  16 //創建一個線程池,將方法排入隊列以便執行

  17 ThreadPool.QueueUserWorkItem(o=> {

  18 lock (ExceptionStringQueue) {

  19 string exceptionString = ExceptionStringQueue.Dequeue();

  20

  21 //發佈

  22 foreach (var writeLog in writeLogList)

  23 {

  24 writeLog.WriteLog(exceptionString);

  25 }

  26

  27 }

  28 });

  29 }

  30

  31

  32 //給外部提供方法,將錯誤信息寫入隊列

  33 public static void Write(string exceptionString) {

  34 lock (ExceptionStringQueue)

  35 {

  36 //將錯誤信息添加到隊列

  37 ExceptionStringQueue.Enqueue(exceptionString);

  38 }

  39 }

  40 }


複製代碼


  後期如果還需要寫入其它地方或者去掉一個的話,只需要Add一個或者刪除一行即可。當然,現在的代碼還有很多可優化的地方,比如把通知者(LogHelper)進行抽象,還可以通過配置文件加反射再次解耦。這裏就不做過多介紹了。因爲已經星期四了...

  星期四

  採用Log4Net

  總結

  觀察者模式又叫發佈-訂閱模式,定義了一種一對多的依賴關係,讓多個觀察者同時監聽同一個對象。當對象狀態發生改變時,通知所訂閱的觀察者。

  什麼時候使用?

  當一個對象改變同時需要改變其他對象,並且還不知道要改變多少對象。這時應該考慮觀察者模式。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章