觀察者模式及事件與委託的區別-20171215內訓會

本文章主要介紹事件與委託的區別以及觀察者模式:c#

1.首先,熟悉c#的人都知道,事件是一種特殊形式的委託,可是說到爲何,應該沒有多少人能說清楚道明白,在學校老師的討論下,咱們對事件進行了一個反編譯,讓咱們知道事件究竟是如何實現的.優化

從這個反編譯看來,事件其實就是封裝了兩個使用委託的方法.一個是添加的,一個是移除的.而它最後的運行仍是使用的委託.spa

-----下面咱們來試着猜一下爲何已經有了委託微軟還要添加事件這個東西-------code

首先,委託是能夠被覆蓋掉的,而且委託能夠直接跳過業務流程直接被調用.blog

 
 
/// <summary> /// 這個類是爲了模仿事件的業務處理 /// </summary>
public class OldBugManager { /// <summary> /// 發送委託 /// </summary>
     /// <param name="name">人名</param>
public delegate void SendDelegate(string name); /// <summary> /// 發送事件 /// </summary> public SendDelegate OldSendEvent; /// <summary> /// 監聽bug的方法 /// </summary> /// <param name="name"></param> public void OldBugMonitor(string name) { //監聽bug開始 //此處省略代碼1萬行 //發生bug if (OldSendEvent != null) { OldSendEvent(name); } //發送完畢的業務代碼開始 //此處省略代碼1千行 //發送完畢的業務代碼結束 } }

上面的方法可讓咱們向委託中存放咱們在特定狀況下要調用的方法.這樣就會出現如下問題事件

 1        EMail email = new EMail();//這個類是發送郵箱的實現類(這裏不須要知道里面幹了什麼事情,只要知道它能夠給某一我的發送EMail,提示修改bug)
 2             Electric electric = new Electric();//這個類是用來電擊提醒的實現類(這裏不須要知道里面幹了什麼事情,只要知道它能夠電擊某一我的,提示修改bug)
 3             string name = "小張";//修改bug的人名
 4             #region 優化前
5 OldBugManager oldBugManager = new OldBugManager();//咱們來實例化一個咱們要調用的事件 6 7 //先來看一看委託爲null的時候不能+= 因此要先判斷委託是不是null 8 if (oldBugManager.OldSendEvent != null) 9 { 10 oldBugManager.OldSendEvent += new OldBugManager.SendDelegate(email.SendEmail); 11 oldBugManager.OldSendEvent += new OldBugManager.SendDelegate(electric.ElectricExec); 12 } 13 else 14 { 15 oldBugManager.OldSendEvent = new OldBugManager.SendDelegate(email.SendEmail);//添加一個發送郵件的委託 16 oldBugManager.OldSendEvent += new OldBugManager.SendDelegate(electric.ElectricExec);//添加一個電擊的委託 17 } 18 #region 引起的問題 19 //這樣作引起的問題 開始 20 oldBugManager.OldSendEvent = new OldBugManager.SendDelegate(MakeTrouble); 21 //1 由於委託暴露因此能夠在外部重寫 22 oldBugManager.OldSendEvent.Invoke(name);
23 // 2 我能夠跳過流程直接執行,由於咱們的監聽方法是OldBugMonitor,這樣就跳過了業務流程直接運行 24 //結束
25 #endregion 26 oldBugManager.OldBugMonitor(name); //監聽bug方法 27 #endregion

-------下面咱們來編寫事件的使用方式---------開發

 public class BugManager
    {
        /// <summary>
        /// 發送委託
        /// </summary>
        public delegate void SendDelegate();
        /// <summary>
        /// 發送事件
        /// </summary>
        public event SendDelegate SendEvent;
        /// <summary>
        /// 監聽bug的方法
        /// </summary>
        public void BugMonitor()
        {
            //監聽bug開始
            //此處省略代碼1萬行
            //發生bug
            if (SendEvent != null)
            {
                SendEvent();
            }
             //發送完畢的業務代碼開始
            //此處省略代碼1千行
            //發送完畢的業務代碼結束
        }
    }

下面是調用事件get

 BugManager bugManage = new BugManager();
 EMail eMail = new EMail(); 
bugManage.SendEvent
+= new BugManager.SendDelegate(eMail.SendEmail); //將發送郵件與bug監聽綁定 Electric electric = new Electric(); bugManage.SendEvent += new BugManager.SendDelegate(electric.ElectricExec);//將電擊與bug監聽綁定 bugManage.BugMonitor(); //觸發事件,這樣的話就不存在跳過業務流程的狀況.

-------------最後咱們模擬一下用委託來實現相似於事件的方法----------------------------string

public class OptimizeBugManager
    {
        /// <summary>
        /// 發送委託
        /// </summary>
        public delegate void SendDelegate(string name);
        /// <summary>
        /// 發送委託
        /// </summary>
        private SendDelegate _OptimizeSendEvent;

        /// <summary>
        /// 添加訂閱者
        /// </summary>
        /// <param name="sendDelegate"></param>
        public void AddSendDelegate(SendDelegate sendDelegate)
        {
            if (sendDelegate != null)
            {
                if (_OptimizeSendEvent != null)
                {
                    _OptimizeSendEvent += sendDelegate;
                }
                else
                {
                    _OptimizeSendEvent = sendDelegate;
                }
            }
           
        }
        /// <summary>
        /// 移除訂閱者
        /// </summary>
        /// <param name="sendDelegate"></param>
        public void RemoveSendDelegate(SendDelegate sendDelegate)
        {
            if (sendDelegate != null)
            {
                if (_OptimizeSendEvent != null)
                {
                    _OptimizeSendEvent -= sendDelegate;
                }
            }
        }
        /// <summary>
        /// 監聽bug的方法
        /// </summary>
        public void OldBugMonitor(string name)
        {
            //監聽bug開始
            //此處省略代碼1萬行
            //發生bug
            if (_OptimizeSendEvent != null)
            {
                _OptimizeSendEvent(name);
            }
            //發送完畢的業務代碼開始
            //此處省略代碼1千行
            //發送完畢的業務代碼結束
        }
    }

這種狀況下由於委託是一個私有的,因此外面除了經過添加和刪除這兩個方法沒法直接對委託進行操做,因此,這樣也不會被重寫也不會跳過應有的業務邏輯來執行事件it

 

而觀察者模式,其實就是說在觸發一個動做的時候能夠去追加一些業務,而不影響原有代碼編寫的一種狀況,上述的代碼其實就是觀察者模式的一種寫法,若是咱們用普通的寫法的時候

咱們可能就要再添加一個邏輯的時候不斷地去修改咱們的業務代碼,形成麻煩.

下面我來編寫一段關於不用觀察者模式的狀況.

    public class BugManager
    {
        /// <summary>
        /// 發生bug的方法
        /// </summary>
        /// <returns></returns>
        public void BugMonitor()
        {
            //監聽bug開始
            //此處省略代碼1萬行
            //發生bug
            SendEmail();//發送郵件
            SendSms();//發送短信
       //!!!!------若是不用觀察者模式咱們就須要不斷地在這個地方去添加方法的調用,咱們的代碼就很差分離,在修改的時候也會容易出錯,不適合團隊的業務開發
//發送完畢的業務代碼開始 //此處省略代碼1千行 //發送完畢的業務代碼結束 } /// <summary> /// 發郵件 /// </summary> public void SendEmail() { Console.WriteLine("發送郵件給A!"); Console.WriteLine("發送郵件給B!"); } /// <summary> /// 發短信 /// </summary> public void SendSms() { Console.WriteLine("發送短信給A!"); Console.WriteLine("發送短信給B!"); } }

  案例地址:連接:https://pan.baidu.com/s/1dFk29KP 密碼:90o8

相關文章
相關標籤/搜索