观察者模式,程序员让被观察者主动通知观察者相应事件的发生,也就存在一个必要的背景,程序员可以获取当前被观察者的状态。
所谓观察者模式,一般采用方法注册,以实现解耦的思维,被观察者内部可注册所有观察者的观察并处理的方法。程序员可以根据当前被观察者的状态来决定是否调用应用观察者的方法。
这么多观察者的事件处理全都是基于被观察者的状态的,当然应该在被观察者这头进行事件处理的调用,我觉得观察者模式里这一条是最重要的,
至于方法注册、抽象接口啥的,完全可以根据当前场景的需求来选择性配置:
高配(注册思维+抽象接口)、低配(for循环+没有抽象接口),下面具体解释:
备注:上述注册思维,一般是结合内核链表来实现,观察者注册观察方法时,通过一个字符串(被观察者对象名字符串)来唯一绑定具体某个被观察者,
某个被观察者遍历调用观察者方法时,只能调用和自身绑定的观察者的方法,不能越界调用其他的观察者的方法。
例如,电梯对象作为观察者要观察楼层按键对象(可以重写下之前的电梯升降小项目,核心思路即:按键对象负责检测用户输入键值,和键值上报到电梯对象?(No, 电梯对象需要从公共通道获取键值。键值直接上报到电梯对象,会造成不同层次间的代码耦合),电梯对象提供上行下行方法,),
通信对象(负责和传达室通信)作为观察者要观察麦克风对象。
当麦克风有输入时,只能调用和自身绑定的观察者,所以需要调用的时通信对象提供的通信方法,而不能调用电梯提供的上行下行方法。
而for循环则无需链表,只需要遍历一个存储观察者方法的函数指针数组即可。
加深理解:
按键作为硬件驱动层,检测用户输入,适合直接调用观察患者们的处理方法吗? 不合适。 第一点:各个观察者的处理方法不一样,有的会阻塞,有的可能不阻塞,直接在按键驱动层调用各个观察者的方法肯定会造成各个观察者方法的拥堵; 第二点: 代码要遵循一定的设计原则,要保持分层,硬件驱动层肯定不能直接调用业务逻辑层的处理。
经过分析后,既然不能直接在硬件驱动层调用观察方法,那么只能够把按键状态上报给各个观察者交由其独立处理了,具体上报给哪个观察者呢? 观察者1,还是观察者2? 这是未知的,甚至是随着业务的扩展有可能会新增观察者。 那么各个观察者肯定需要一个公共的通道来获取这个键值,即便新增观察者,也只需要从该公共通道来获取键值即可, 所以工程中肯定需要一个队列。 键值从按键驱动层入队,出队时调用各个观察者的处理方法。该层可以理解为观察者和被观察者的中间hal层。
那么如何保证出队时不造成各个观察者处理方法的拥堵呢? 使用多线程,各个观察者处理方法内仅仅是发送一个信号来触发各自观察者线程的实际针对按键的处理线程,这样可以达到并行的处理。
联系register_input_status_listener 该注册方法和 input_status_report_handler该被注册的观察者方法,
参考input子系统实现原理。
.
原文:https://www.cnblogs.com/happybirthdaytoyou/p/13515286.html