翼度科技»论坛 编程开发 .net 查看内容

C#事件(event)的理解

10

主题

10

帖子

30

积分

新手上路

Rank: 1

积分
30
一、多播委托的应用--观察者模式

遇到一个开发的问题?
面试者:以面向对象的思想实现一下的场景:
猫:Miao一声,紧接着引发了一系列的行为~
Miao:引发了一系列的动作;
从代码层面来说:代码这样写好吗?

  • 猫职责不单一(猫就是猫,他的行为只有Miao一声)
  • 依赖太重,依赖了很多的普通类;   被依赖的类如果修改,可能会引发这个猫也要修改;---代码不稳定;
  • 如果要控制顺序---也要修改代码; 有新需求,必须要修改历史代码---开闭原则;
从传统的方式去考虑的话,我们可能会写出来这个如此这样的代码
  1. class Dog
  2. {
  3.     public void Bark()
  4.     {
  5.         Console.WriteLine("Dog Bark!");
  6.     }
  7. }
  8. class Fox
  9. {
  10.     public void Eat()
  11.     {
  12.         Console.WriteLine("Fox Eat!");
  13.     }
  14.    
  15. }
  16. class Cat
  17. {
  18.     public void Miao()
  19.     {
  20.         new Fox().Eat();
  21.         new Dog().Bark();
  22.         Console.WriteLine("Cat Miao!");
  23.     }
  24. }
复制代码
从代码层面来说:代码这样写好吗?

  • 猫职责不单一(猫就是猫,他的行为只有Miao一声)
  • 依赖太重,依赖了很多的普通类;   被依赖的类如果修改,可能会引发这个猫也要修改;---代码不稳定;
  • 如果要控制顺序---也要修改代码; 有新需求,必须要修改历史代码---开闭原则;
如何解决呢?  第一个问题:让猫的职责单一,  后续触发的行为,猫Miao一声之后,只负责触发; 触发的是一堆的行为;
请问:如果要希望在触发一个行为后,能够执行多个行为,执行一系列的行为?? 怎么办?-------多播委托;
核心:把依赖的东西转移到上端,保证当前类的稳定; ----可以做到解耦
二者实现本质:是相通的;  都是类似于一个盒子, OOP: 盒子中装对象     委托:盒子装方法;
通过OOP 继承实现的ObServer
IObject.cs
  1. public interface IObject
  2. {
  3.      public void DoAction();
  4. }
复制代码
Baby.cs
  1. public class Baby:IObject
  2. {
  3.    public void Cry()
  4.     {
  5.         Console.WriteLine("Baby Cry");
  6.     }
  7.     public void DoAction()
  8.     {
  9.         Cry();
  10.     }
  11. }
复制代码
Brother.cs
  1. public class Brother:IObject
  2. {
  3.      public void Turn()
  4.      {
  5.          Console.WriteLine("Brother Turn");
  6.      }
  7.      public void DoAction()
  8.      {
  9.          Turn();
  10.      }
  11. }
复制代码
Dog.cs
  1. public class Dog:IObject
  2. {
  3.      public void Wang()
  4.      {
  5.          Console.WriteLine("Dog Wang");
  6.      }
  7.      public void DoAction()
  8.      {
  9.          Wang();
  10.      }
  11. }
复制代码
Father.cs
  1. public class Father:IObject
  2. {
  3.      public void Roar()
  4.      {
  5.          Console.WriteLine("Father Roar");
  6.      }
  7.      public void DoAction()
  8.      {
  9.          Roar();
  10.      }
  11. }
复制代码
Mother.cs
  1. public class Mother:IObject
  2. {
  3.      public void Wispher()
  4.      {
  5.          Console.WriteLine("Mother Wispher");
  6.      }
  7.      public void DoAction()
  8.      {
  9.          Wispher();
  10.      }
  11. }
复制代码
Mouse.cs
  1. public class Mouse:IObject
  2. {
  3.      public void Run()
  4.      {
  5.          Console.WriteLine("Mouse Run");
  6.      }
  7.      public void DoAction()
  8.      {
  9.          Run();
  10.      }
  11. }
复制代码
Neighbor.cs
  1. public class Neighbor:IObject
  2. {
  3.     public void Awake()
  4.     {
  5.         Console.WriteLine("Neighbor Awake");
  6.     }
  7.     public void DoAction()
  8.     {
  9.         Awake();
  10.     }
  11. }
复制代码
Stealer.cs
  1. public class Stealer:IObject
  2. {
  3.     public void Hide()
  4.     {
  5.         Console.WriteLine("Stealer Hide");
  6.     }
  7.     public void DoAction()
  8.     {
  9.         Hide();
  10.     }
  11. }
复制代码
Cat.cs
  1. public class Cat
  2. {  
  3.     public List<IObject> ObserList=new List<IObject>();
  4.     public void MiaoObserver()
  5.     {
  6.         Console.WriteLine($"{this.GetType().Name} MiaoObserver========");
  7.         foreach ( IObject item in ObserList )
  8.         {
  9.             item.DoAction();
  10.         }
  11.     }
  12. }
复制代码
Progarm.cs
  1. Console.WriteLine("=========================================");
  2. Console.WriteLine("=========================================");
  3. {
  4.     Cat cat = new Cat();
  5.     cat.objects.Add(new Baby());
  6.     cat.objects.Add(new Mother());
  7.     cat.objects.Add(new Dog());
  8.     cat.objects.Add(new Mouse());
  9.     cat.objects.Add(new Father());
  10.     cat.objects.Add(new Neighbor());
  11.     cat.objects.Add(new Stealer());
  12.     cat.objects.Add(new Brother());
  13.     cat.MiaoObserver();
  14. }
  15. Console.WriteLine("=========================================");
  16. Console.WriteLine("=========================================");
复制代码
通过委托实现
cat.cs
  1. public Action? MiaoDelegate;
  2. public void MiaoDelegateObserver()
  3. {
  4.     Console.WriteLine($"{this.GetType().Name} MiaoDelegateObserver========");
  5.     if (MiaoDelegate != null)
  6.     {
  7.         MiaoDelegate();
  8.     }
  9. }
复制代码
program.cs
  1. Console.WriteLine("=========================================");
  2. Console.WriteLine("=========================================");
  3. {
  4.     Cat cat = new Cat();
  5.     cat.MiaoDelegate += new Baby().Cry;
  6.     cat.MiaoDelegate += new Mother().Wispher;
  7.     cat.MiaoDelegate += new Dog().Wang;
  8.     cat.MiaoDelegate += new Mouse().Run;
  9.     cat.MiaoDelegate += new Father().Roar;
  10.     cat.MiaoDelegate += new Neighbor().Awake;
  11.     cat.MiaoDelegate += new Stealer().Hide;
  12.     cat.MiaoDelegate += new Brother().Turn;
  13.     //cat.ActionHander -= new Baby().Cry;
  14.     //  cat.ActionHander.Invoke();// 委托可以在定义委托所在类的外部去执行;
  15.     cat.MiaoDelegateObserver();
  16. }
  17. Console.WriteLine("=========================================");
  18. Console.WriteLine("=========================================");
复制代码
通过事件实现
cat.cs
  1. public event Action ActionHanderEvent;   
  2. public void MiaoEvent()
  3. {
  4.     Console.WriteLine($"{this.GetType().Name} MiaoEvent========");
  5.     ActionHanderEvent.Invoke();   //这个行为要一定是执行 MiaoEvent方法的时候才触发的;
  6. }
复制代码
program.cs
  1. Console.WriteLine("事件的应用:============================");
  2. {
  3.      Cat cat = new Cat();
  4.      cat.ActionHanderEvent += new Baby().Cry;
  5.      cat.ActionHanderEvent += new Mother().Wispher;
  6.      cat.ActionHanderEvent += new Dog().Wang;
  7.      cat.ActionHanderEvent += new Mouse().Run;
  8.      cat.ActionHanderEvent += new Father().Roar;
  9.      cat.ActionHanderEvent += new Neighbor().Awake;
  10.      cat.ActionHanderEvent += new Stealer().Hide;
  11.      // cat.ActionHanderEvent -= new Baby().Cry;
  12.      //cat.ActionHanderEvent.Invoke();
  13.      cat.MiaoEvent ();
  14. }
复制代码
什么是事件,其实就是委托的实例+关键字; 事件是一个特殊的委托;
委托和事件有什么区别?
1 多个了关键字
2 事件的权限控制会更加严格--事件的执行,只能,必须在声明这个事件所在的类的内部才能执行;
已经有了委托,为什么还要事件呢?----在系统框架设计中,需要这样的权限控制;
已经有了委托,为什么还要事件呢?----在系统框架设计中,需要这样的权限控制;
使用winform程序来做示范

登录
思路:按钮点击会触发这个方法,如果是通过事件来完成,必然会有一个地方定义得有事件,还要把这个方法给注册到事件中去;
执行的逻辑:在按钮初始化的时候,把按钮中的Click 指向一个方法btnLogin_Click;
运行起来: 鼠标点击按钮----操作系统可以捕捉到鼠标的信号,通过句柄判断,确定是哪个程序,通过程序中句柄判断是按个一个组件(按钮),可以获取到按钮的实例; 得到的是登录按钮;   鼠标单机左键信号,按钮
委托和事件的功能差不多---按钮的点击后触发的行为,为什么用事件而不用委托?????
就是为了要管控这个按钮,只能在特定的情况下去执行;
如果用委托:委托就可以在外部去执行;
点击登录,触发登录的方法----必须是点击登录后触发  所以只能用事件而不能用委托
点击注册,触发注册的方法----必须是点击注册后触发   所以只能用事件而不能用委托
不能通过任何其他别的渠道来触发这个方法
如果我使用委托:尽管一在点击了按钮之后,可以触发对应的行为,但是委托没有权限的限制,就可以在外部执行这个委托----不允许的;保证动作触发的来源一定是来自于哪里;
委托和事件的相通性:
二者功能差不多,观察者;在程序中,除了保证代码的问题;
其他场景
三个按钮---鼠标指向---变颜色(按钮的行为); 所有的按钮都有这个行为; 而单单只有登录和注册--点击后可以触发对应的方法;因为给这两个按钮的Click事件注册了行为;
在系统的框架中,如果有一段逻辑的执行; 其中有一些通用的逻辑(三个按钮都有执向变颜色),还有一些个性化的逻辑,每个按钮点击后可能需要执行不同的逻辑;  可以通过事件来进行注册;
价值: 可以把通用的逻辑封装
把可变的逻辑通过事件注册
执行来了,通用逻辑(统一的代码执行)-----可变的逻辑(各自执行各自的~·) 程序可以更加灵活~~ Web--- ASP.NET MVC管道处理模型~~
2.定义事件+实现发布订阅

1.朝夕要发布新课程,嵌入式和C++ Qt (都是Richard老师给大家上课)
2.很多小伙伴们很期待,很关注
3.如果课程发布,根据需求报名学习
  1. public class EventStandard
  2. {
  3.      private static PublicCourse publicCourse1 = new PublicCourse()
  4.      {
  5.          Id = 222,
  6.          Name = "Qt和C++",
  7.      };
  8.      private static PublicCourse publicCourse2 = new PublicCourse()
  9.      {
  10.          Id = 222,
  11.          Name = "嵌入式开发",
  12.      };
  13.       
  14.      /// <summary>
  15.      /// 发布课程
  16.      /// </summary>
  17.      public static void Show()
  18.      {
  19.          publicCourse1.PublicShow();// 只关注发布,发布后,会有后续的行为
  20.          publicCourse2.PublicShow();
  21.      }
  22.      /// <summary>
  23.      /// 初始化订阅者和发布者之间的关系( 订阅中心 )
  24.      /// </summary>
  25.      public static void Init()
  26.      {
  27.          StudentUser user1 = new StudentUser()
  28.          {
  29.              Id = 123,
  30.              Name = "夕林吹雪"
  31.          };
  32.          publicCourse1.Publish += user1.Buy;
  33.          publicCourse2.Publish += user1.Buy;
  34.       
  35.          StudentUser user2 = new StudentUser()
  36.          {
  37.              Id = 123,
  38.              Name = "张三"
  39.          };
  40.          publicCourse1.Publish += user2.Buy;
  41.          publicCourse2.Publish += user2.Buy;
  42.          StudentUser user3 = new StudentUser()
  43.          {
  44.              Id = 123,
  45.              Name = "李四"
  46.          };
  47.          publicCourse1.Publish += user3.Buy;
  48.          publicCourse2.Publish += user3.Buy;
  49.      }
  50. }
  51. /// <summary>
  52. /// 发布者
  53. /// 发布后,就会有后续的逻辑---具体是什么,不知道
  54. /// </summary>
  55. public class PublicCourse
  56. {
  57.      public int Id { get; set; }
  58.      public string Name { get; set; }
  59.      public void PublicShow()
  60.      {
  61.          Console.WriteLine("朝夕新课程发布: Qt+C++  嵌入式开发~~~");
  62.          //会有很多的人关注
  63.          //会有很多的后续动作执行, 有人咨询,有人报名,有人体验课程~
  64.          Publish.Invoke(this, new CourseInfo()
  65.          {
  66.              Id=345,
  67.              Title="Qt和 C++"
  68.          });
  69.      }
  70.      public event EventHandler Publish;
  71. }
  72. /// <summary>
  73. /// 订阅者(订户):
  74. /// 订阅消息,消息出现,就会触发行为;
  75. /// </summary>
  76. public class StudentUser
  77. {
  78.      public int Id { get; set; }
  79.      public string Name { get; set; }
  80.      public void Buy(object? sender, EventArgs e)
  81.      {
  82.          PublicCourse  course= (PublicCourse)(sender);
  83.          Console.WriteLine($"朝夕有新的课程发布,可称为{course.Name}");
  84.          Console.WriteLine($"用户:{Name}先了解下,考虑考虑");
  85.          Console.WriteLine($"可以购买学习~~");
  86.      }
  87. }
  88. /// <summary>
  89. /// 扩展参数
  90. /// </summary>
  91. public class CourseInfo : EventArgs
  92. {
  93.      public int Id { get; set; }
  94.      public string Title { get; set; }
  95.      public string Description { get; set; }
  96.      public string TeacherWechatNum { get; set; }
  97. }
复制代码
来源:https://www.cnblogs.com/wenlong-4613615/p/18060390
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具