在"實現觀察者模式(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();}
□ 體驗委託與事件的區別
現在,我們在客戶端,在呼叫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();}
可見,當把把Referee的委託變數DoSth設定為null後,所有註冊的方法將得不到執行。
如果把Referee的委託變數DoSth修飾為事件。
public class Referee{public event Action DoSth;public void ISayGameOver(){Console.WriteLine("嘀嘀嘀......比賽結束了~~");
if (DoSth != null){DoSth();}}}
可見,當把委託變數DoSth修飾為事件後,只能通過+=和-=註冊、取消方法,不能通過=設定。
把referee.DoSth = null;註釋掉,將不會報錯。
“委託、Lambda表示式、事件系列”包括: