|
一、多播委托的应用--观察者模式
遇到一个开发的问题?
面试者:以面向对象的思想实现一下的场景:
猫:Miao一声,紧接着引发了一系列的行为~
Miao:引发了一系列的动作;
从代码层面来说:代码这样写好吗?
- 猫职责不单一(猫就是猫,他的行为只有Miao一声)
- 依赖太重,依赖了很多的普通类; 被依赖的类如果修改,可能会引发这个猫也要修改;---代码不稳定;
- 如果要控制顺序---也要修改代码; 有新需求,必须要修改历史代码---开闭原则;
从传统的方式去考虑的话,我们可能会写出来这个如此这样的代码- class Dog
- {
- public void Bark()
- {
- Console.WriteLine("Dog Bark!");
- }
- }
- class Fox
- {
- public void Eat()
- {
- Console.WriteLine("Fox Eat!");
- }
-
- }
- class Cat
- {
- public void Miao()
- {
- new Fox().Eat();
- new Dog().Bark();
- Console.WriteLine("Cat Miao!");
- }
- }
复制代码 从代码层面来说:代码这样写好吗?
- 猫职责不单一(猫就是猫,他的行为只有Miao一声)
- 依赖太重,依赖了很多的普通类; 被依赖的类如果修改,可能会引发这个猫也要修改;---代码不稳定;
- 如果要控制顺序---也要修改代码; 有新需求,必须要修改历史代码---开闭原则;
如何解决呢? 第一个问题:让猫的职责单一, 后续触发的行为,猫Miao一声之后,只负责触发; 触发的是一堆的行为;
请问:如果要希望在触发一个行为后,能够执行多个行为,执行一系列的行为?? 怎么办?-------多播委托;
核心:把依赖的东西转移到上端,保证当前类的稳定; ----可以做到解耦
二者实现本质:是相通的; 都是类似于一个盒子, OOP: 盒子中装对象 委托:盒子装方法;
通过OOP 继承实现的ObServer
IObject.cs- public interface IObject
- {
- public void DoAction();
- }
复制代码 Baby.cs- public class Baby:IObject
- {
- public void Cry()
- {
- Console.WriteLine("Baby Cry");
- }
- public void DoAction()
- {
- Cry();
- }
- }
复制代码 Brother.cs- public class Brother:IObject
- {
- public void Turn()
- {
- Console.WriteLine("Brother Turn");
- }
- public void DoAction()
- {
- Turn();
- }
- }
复制代码 Dog.cs- public class Dog:IObject
- {
- public void Wang()
- {
- Console.WriteLine("Dog Wang");
- }
- public void DoAction()
- {
- Wang();
- }
- }
复制代码 Father.cs- public class Father:IObject
- {
- public void Roar()
- {
- Console.WriteLine("Father Roar");
- }
- public void DoAction()
- {
- Roar();
- }
- }
复制代码 Mother.cs- public class Mother:IObject
- {
- public void Wispher()
- {
- Console.WriteLine("Mother Wispher");
- }
- public void DoAction()
- {
- Wispher();
- }
- }
复制代码 Mouse.cs- public class Mouse:IObject
- {
- public void Run()
- {
- Console.WriteLine("Mouse Run");
- }
- public void DoAction()
- {
- Run();
- }
- }
复制代码 Neighbor.cs- public class Neighbor:IObject
- {
- public void Awake()
- {
- Console.WriteLine("Neighbor Awake");
- }
- public void DoAction()
- {
- Awake();
- }
- }
复制代码 Stealer.cs- public class Stealer:IObject
- {
- public void Hide()
- {
- Console.WriteLine("Stealer Hide");
- }
- public void DoAction()
- {
- Hide();
- }
- }
复制代码 Cat.cs- public class Cat
- {
- public List<IObject> ObserList=new List<IObject>();
- public void MiaoObserver()
- {
- Console.WriteLine($"{this.GetType().Name} MiaoObserver========");
- foreach ( IObject item in ObserList )
- {
- item.DoAction();
- }
- }
- }
复制代码 Progarm.cs- Console.WriteLine("=========================================");
- Console.WriteLine("=========================================");
- {
- Cat cat = new Cat();
- cat.objects.Add(new Baby());
- cat.objects.Add(new Mother());
- cat.objects.Add(new Dog());
- cat.objects.Add(new Mouse());
- cat.objects.Add(new Father());
- cat.objects.Add(new Neighbor());
- cat.objects.Add(new Stealer());
- cat.objects.Add(new Brother());
- cat.MiaoObserver();
- }
- Console.WriteLine("=========================================");
- Console.WriteLine("=========================================");
复制代码 通过委托实现
cat.cs- public Action? MiaoDelegate;
- public void MiaoDelegateObserver()
- {
- Console.WriteLine($"{this.GetType().Name} MiaoDelegateObserver========");
- if (MiaoDelegate != null)
- {
- MiaoDelegate();
- }
- }
复制代码 program.cs- Console.WriteLine("=========================================");
- Console.WriteLine("=========================================");
- {
- Cat cat = new Cat();
- cat.MiaoDelegate += new Baby().Cry;
- cat.MiaoDelegate += new Mother().Wispher;
- cat.MiaoDelegate += new Dog().Wang;
- cat.MiaoDelegate += new Mouse().Run;
- cat.MiaoDelegate += new Father().Roar;
- cat.MiaoDelegate += new Neighbor().Awake;
- cat.MiaoDelegate += new Stealer().Hide;
- cat.MiaoDelegate += new Brother().Turn;
- //cat.ActionHander -= new Baby().Cry;
- // cat.ActionHander.Invoke();// 委托可以在定义委托所在类的外部去执行;
- cat.MiaoDelegateObserver();
- }
- Console.WriteLine("=========================================");
- Console.WriteLine("=========================================");
复制代码 通过事件实现
cat.cs- public event Action ActionHanderEvent;
- public void MiaoEvent()
- {
- Console.WriteLine($"{this.GetType().Name} MiaoEvent========");
- ActionHanderEvent.Invoke(); //这个行为要一定是执行 MiaoEvent方法的时候才触发的;
- }
复制代码 program.cs- Console.WriteLine("事件的应用:============================");
- {
- Cat cat = new Cat();
- cat.ActionHanderEvent += new Baby().Cry;
- cat.ActionHanderEvent += new Mother().Wispher;
- cat.ActionHanderEvent += new Dog().Wang;
- cat.ActionHanderEvent += new Mouse().Run;
- cat.ActionHanderEvent += new Father().Roar;
- cat.ActionHanderEvent += new Neighbor().Awake;
- cat.ActionHanderEvent += new Stealer().Hide;
- // cat.ActionHanderEvent -= new Baby().Cry;
- //cat.ActionHanderEvent.Invoke();
- cat.MiaoEvent ();
- }
复制代码 什么是事件,其实就是委托的实例+关键字; 事件是一个特殊的委托;
委托和事件有什么区别?
1 多个了关键字
2 事件的权限控制会更加严格--事件的执行,只能,必须在声明这个事件所在的类的内部才能执行;
已经有了委托,为什么还要事件呢?----在系统框架设计中,需要这样的权限控制;
已经有了委托,为什么还要事件呢?----在系统框架设计中,需要这样的权限控制;
使用winform程序来做示范
登录
思路:按钮点击会触发这个方法,如果是通过事件来完成,必然会有一个地方定义得有事件,还要把这个方法给注册到事件中去;
执行的逻辑:在按钮初始化的时候,把按钮中的Click 指向一个方法btnLogin_Click;
运行起来: 鼠标点击按钮----操作系统可以捕捉到鼠标的信号,通过句柄判断,确定是哪个程序,通过程序中句柄判断是按个一个组件(按钮),可以获取到按钮的实例; 得到的是登录按钮; 鼠标单机左键信号,按钮
委托和事件的功能差不多---按钮的点击后触发的行为,为什么用事件而不用委托?????
就是为了要管控这个按钮,只能在特定的情况下去执行;
如果用委托:委托就可以在外部去执行;
点击登录,触发登录的方法----必须是点击登录后触发 所以只能用事件而不能用委托
点击注册,触发注册的方法----必须是点击注册后触发 所以只能用事件而不能用委托
不能通过任何其他别的渠道来触发这个方法
如果我使用委托:尽管一在点击了按钮之后,可以触发对应的行为,但是委托没有权限的限制,就可以在外部执行这个委托----不允许的;保证动作触发的来源一定是来自于哪里;
委托和事件的相通性:
二者功能差不多,观察者;在程序中,除了保证代码的问题;
其他场景
三个按钮---鼠标指向---变颜色(按钮的行为); 所有的按钮都有这个行为; 而单单只有登录和注册--点击后可以触发对应的方法;因为给这两个按钮的Click事件注册了行为;
在系统的框架中,如果有一段逻辑的执行; 其中有一些通用的逻辑(三个按钮都有执向变颜色),还有一些个性化的逻辑,每个按钮点击后可能需要执行不同的逻辑; 可以通过事件来进行注册;
价值: 可以把通用的逻辑封装
把可变的逻辑通过事件注册
执行来了,通用逻辑(统一的代码执行)-----可变的逻辑(各自执行各自的~·) 程序可以更加灵活~~ Web--- ASP.NET MVC管道处理模型~~
2.定义事件+实现发布订阅
1.朝夕要发布新课程,嵌入式和C++ Qt (都是Richard老师给大家上课)
2.很多小伙伴们很期待,很关注
3.如果课程发布,根据需求报名学习- public class EventStandard
- {
- private static PublicCourse publicCourse1 = new PublicCourse()
- {
- Id = 222,
- Name = "Qt和C++",
- };
- private static PublicCourse publicCourse2 = new PublicCourse()
- {
- Id = 222,
- Name = "嵌入式开发",
- };
-
- /// <summary>
- /// 发布课程
- /// </summary>
- public static void Show()
- {
- publicCourse1.PublicShow();// 只关注发布,发布后,会有后续的行为
- publicCourse2.PublicShow();
- }
- /// <summary>
- /// 初始化订阅者和发布者之间的关系( 订阅中心 )
- /// </summary>
- public static void Init()
- {
- StudentUser user1 = new StudentUser()
- {
- Id = 123,
- Name = "夕林吹雪"
- };
- publicCourse1.Publish += user1.Buy;
- publicCourse2.Publish += user1.Buy;
-
- StudentUser user2 = new StudentUser()
- {
- Id = 123,
- Name = "张三"
- };
- publicCourse1.Publish += user2.Buy;
- publicCourse2.Publish += user2.Buy;
- StudentUser user3 = new StudentUser()
- {
- Id = 123,
- Name = "李四"
- };
- publicCourse1.Publish += user3.Buy;
- publicCourse2.Publish += user3.Buy;
- }
- }
- /// <summary>
- /// 发布者
- /// 发布后,就会有后续的逻辑---具体是什么,不知道
- /// </summary>
- public class PublicCourse
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public void PublicShow()
- {
- Console.WriteLine("朝夕新课程发布: Qt+C++ 嵌入式开发~~~");
- //会有很多的人关注
- //会有很多的后续动作执行, 有人咨询,有人报名,有人体验课程~
- Publish.Invoke(this, new CourseInfo()
- {
- Id=345,
- Title="Qt和 C++"
- });
- }
- public event EventHandler Publish;
- }
- /// <summary>
- /// 订阅者(订户):
- /// 订阅消息,消息出现,就会触发行为;
- /// </summary>
- public class StudentUser
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public void Buy(object? sender, EventArgs e)
- {
- PublicCourse course= (PublicCourse)(sender);
- Console.WriteLine($"朝夕有新的课程发布,可称为{course.Name}");
- Console.WriteLine($"用户:{Name}先了解下,考虑考虑");
- Console.WriteLine($"可以购买学习~~");
- }
- }
- /// <summary>
- /// 扩展参数
- /// </summary>
- public class CourseInfo : EventArgs
- {
- public int Id { get; set; }
- public string Title { get; set; }
- public string Description { get; set; }
- public string TeacherWechatNum { get; set; }
- }
复制代码 来源:https://www.cnblogs.com/wenlong-4613615/p/18060390
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|