委託、Lambda表示式、事件系列06,使用Action實現觀察者模式,體驗委託和事件的區別

Darren Ji發表於2014-10-02

在"實現觀察者模式(Observer Pattern)的2種方式"中,曾經通過介面的方式、委託與事件的方式實現過觀察者模式。本篇體驗使用Action實現此模式,並從中體驗委託與事件的區別。

 

□ 使用Action實現觀察者模式

 

就舉一個足球場上的例子,當裁判吹響終場哨,勝隊慶祝,失敗隊落寞。把裁判看作是被觀察者,比賽中的兩隊看作是觀察者。

 

裁判作為被觀察者需要提供一個Action委託供觀察者方法註冊。

    public class Referee
    {
        public Action DoSth;
        public void ISayGameOver()
        {
            Console.WriteLine("嘀嘀嘀......比賽結束了~~");
            DoSth();
        }
    }

 

勝利的隊和失敗的隊擁有共同的基類。

    public class Team
    {
        private string _name;
        public Team(string name)
        {
            _name = name;
        }
        public string Name
        {
            get { return _name; }
        }
    }

 

勝利隊或失敗隊,作為觀察者,必須有符合Referee中Action定義的方法。

    public class WinTeam : Team
    {
        public WinTeam(string name) : base(name){}
        public void Celebrate()
        {
            Console.WriteLine("我們晉級了,好開心!");
        }
    }
    public class LoseTeam : Team
    {
        public LoseTeam(string name) : base(name){}
        public void WeAreSad()
        {
            Console.WriteLine("比賽輸了,好傷心!");
        }
    }

 

客戶端,先把失敗隊和勝利隊的方法註冊到Action變數,然後由被觀察者的一個方法觸發委託鏈和方法。

        static void Main(string[] args)
        {
            Referee referee = new Referee();
            var winTeam = new WinTeam("勝利隊");
            var loseTeam = new LoseTeam("失敗隊");
            //註冊觀察者
            referee.DoSth += winTeam.Celebrate;
            referee.DoSth += loseTeam.WeAreSad;
            //被觀察者啟動事件通知觀察者
            referee.ISayGameOver();
        } 

16

 

□ 體驗委託與事件的區別

 

現在,我們在客戶端,在呼叫Referee的例項方法ISayGameOver之前,嘗試把Referee的委託變數DoSth設定為null。

        static void Main(string[] args)
        {
            Referee referee = new Referee();
            var winTeam = new WinTeam("勝利隊");
            var loseTeam = new LoseTeam("失敗隊");
            //註冊觀察者
            referee.DoSth += winTeam.Celebrate;
            referee.DoSth += loseTeam.WeAreSad;
            referee.DoSth = null;
            //被觀察者啟動事件通知觀察者
            referee.ISayGameOver();
        }

17
可見,當把把Referee的委託變數DoSth設定為null後,所有註冊的方法將得不到執行。

 

如果把Referee的委託變數DoSth修飾為事件。

    public class Referee
    {
        public event Action DoSth;
        public void ISayGameOver()
        {
            Console.WriteLine("嘀嘀嘀......比賽結束了~~");
            if (DoSth != null)
            {
                DoSth();
            }
            
        }
    }

18
可見,當把委託變數DoSth修飾為事件後,只能通過+=和-=註冊、取消方法,不能通過=設定。

 

把referee.DoSth = null;註釋掉,將不會報錯。  

 

“委託、Lambda表示式、事件系列”包括:

委託、Lambda表示式、事件系列01,委託是什麼,委託的基本用法,委託的Method和Target屬性

委託、Lambda表示式、事件系列02,什麼時候該用委託

委託、Lambda表示式、事件系列03,從委託到Lamda表示式

委託、Lambda表示式、事件系列04,委託鏈是怎樣形成的, 多播委託, 呼叫委託鏈方法,委託鏈異常處理

委託、Lambda表示式、事件系列05,Action委託與閉包

委託、Lambda表示式、事件系列06,使用Action實現觀察者模式,體驗委託和事件的區別

委託、Lambda表示式、事件系列07,使用EventHandler委託

相關文章