C#委托和事件实现观察者模式
需求背景
猫叫触发一系列的动作或者说触发一系列事件,猫叫导致狗叫,小孩哭,Mom跑。
代码结构申明
1 /// <summary> 2 /// 接口类 3 /// </summary> 4 public interface IObeject 5 { 6 /// <summary> 7 /// 提供该方法执行一系列继承自该接口的类行为 8 /// </summary> 9 void DoAction(); 10 }
1 /// <summary> 2 /// 狗类 3 /// </summary> 4 public class Dog : IObeject 5 { 6 public void DoAction() 7 { 8 this.Wang(); 9 } 10 /// <summary> 11 /// 狗叫 12 /// </summary> 13 public void Wang() { 14 Console.WriteLine("狗叫了..."); 15 } 16 }
1 /// <summary> 2 /// 孩子类 3 /// </summary> 4 public class Baby : IObeject 5 { 6 public void DoAction() 7 { 8 this.Cry(); 9 } 10 /// <summary> 11 /// 小孩吓哭了 12 /// </summary> 13 public void Cry() { 14 Console.WriteLine("小孩吓哭了"); 15 } 16 17 }
/// <summary> /// Mom类 /// </summary> public class Mom : IObeject { public void DoAction() { this.Run(); } /// <summary> /// 妈妈跑 /// </summary> public void Run() { Console.WriteLine("妈妈着急了,Mom Run..."); } }
1 /// <summary> 2 /// 猫类 3 /// </summary> 4 public class Cat 5 { 6 /// <summary> 7 /// Cat类依赖了多种类型,任何猫类依赖的类型变化都与猫有关,猫类甚至还要控制事件的执行顺序。 8 /// 如果事件需要调整顺序,或者猫依赖的类发生变化都得修改猫类的代码,类与类之间的关系严重耦合。且职责不单一 9 /// 实际上不该如此,猫就是猫,猫只负责Miao,猫只做自己的事,别的事与我无关,需求就是猫Miao了一声,触发一系列 10 /// 动作,至于触发什么动作,与猫无关。 11 /// </summary> 12 public void Miao() 13 { 14 Console.WriteLine("猫叫了一声..."); 15 new Dog().Wang(); 16 new Baby().Cry(); 17 new Mom().Run(); 18 } 19 20 private IList<IObeject> _ObserverList = new List<IObeject>(); 21 22 public void AddObserver(IObeject obeserver) { 23 this._ObserverList.Add(obeserver); 24 } 25 26 public void MiaoObserver() { 27 28 foreach (var _obeserver in _ObserverList) 29 { 30 _obeserver?.DoAction(); 31 } 32 } 33 34 #region 使用委托 35 public Action CatMiaoAction; 36 37 public void MiaoDelegate() { 38 39 this.CatMiaoAction?.Invoke(); 40 } 41 #endregion 42 43 #region 使用事件 44 /// <summary> 45 /// 什么是事件?事件是委托的一个实例,如Student的一个实例是张三,并且带有event关键字修饰,事件是一种更安全的特殊委托 46 /// 只能在事件所在的类内部对其赋值和调用(invoke();),不能在外部对其赋值和调用,即使是子类。 47 /// </summary> 48 public event Action CatMiaoActionEvent; 49 50 public void MiaoDelegateHandler() 51 { 52 //this.CatMiaoActionEvent = null;//编译可以通过 53 this.CatMiaoActionEvent?.Invoke();//编译可以通过 54 } 55 #endregion 56 } 57 58 public class MiniCat : Cat 59 { 60 public void Do() 61 { 62 //this.CatMiaoActionEvent = null;//即使是子类,编译不通过,不能赋值 63 //this.CatMiaoActionEvent?.invoke();//即使是子类,编译不通过,不能调用 64 } 65 }
1 static void Main(string[] args) 2 { 3 { 4 new Cat().Miao(); 5 } 6 { 7 //去除了猫类对其它类的依赖,把依赖通过抽象转移到外部,事件的触发逻辑交给调用者,与猫 8 //无关,猫作为事件发布者,这是一种观察者模式的运用 9 Cat cat = new Cat(); 10 cat.AddObserver(new Dog()); 11 cat.AddObserver(new Baby()); 12 cat.AddObserver(new Mom()); 13 cat.MiaoObserver(); 14 Console.WriteLine("**********"); 15 } 16 { 17 //使用委托和事件的方式解决该问题,去除了Cat的依赖,Cat稳定了,还可以有多个Cat.CatMiaoAction的实例 18 Cat cat = new Cat(); 19 cat.CatMiaoAction += new Dog().Wang; 20 cat.CatMiaoAction += new Baby().Cry; 21 cat.CatMiaoAction += new Mom().Run; 22 cat.MiaoDelegate(); 23 Console.WriteLine("**********"); 24 } 25 { 26 //使用委托和事件的方式解决该问题,去除了Cat的依赖,Cat稳定了,还可以有多个Cat.CatMiaoActionEvent的实例 27 Cat cat = new Cat(); 28 cat.CatMiaoActionEvent += new Dog().Wang; 29 cat.CatMiaoActionEvent += new Baby().Cry; 30 cat.CatMiaoActionEvent += new Mom().Run; 31 cat.MiaoDelegateHandler(); 32 Console.WriteLine("**********"); 33 } 34 Console.ReadLine(); 35 }
欢迎评论留言交流