• 观察者模式


    观察者模式常用于一对多的监听情景,并且被监听者可以实现监听者的回调,也就是说被监听者能够触发监听者的动作,该动作就是回调。

    观察者模式的特点:

    1.被观察者不知道具体的观察者是谁,只知道自己被观察了,并且在合适的时机进行广播,让感兴趣的观察者知道发生了什么事情。

    2.观察者依赖于被观察者,被观察者不依赖于观察者,是单向关系,耦合程度不高。没有被观察者,观察者无法工作;没有观察者,被观察者该干啥干啥,因为被观察者本来就不清楚谁观察他,发广播是被观察的个人行为。

    3.通常被观察者出现行为上的变化,需要观察者做出反馈。显然一般情况下观察者并不知道被观察者啥时候会有变化,因此该反馈是一种被动反馈,实现的是一种回调机制。

    观察者

    1. package com.example.listenertest;
    2. public abstract class Observer {
    3. //添加被观察者的引用
    4. protected Subject subject;
    5. //更新的抽象方法
    6. public abstract void update();
    7. }

    通常观察者需要一个共有的父类,通常为抽象类。

    可见,观察者是依赖于被观察者的,观察者必须有一个具体的被观察者的引用,自身才能实例化。

    此外,update函数就是观察者做出的反馈,是被被观察者调用的,因此是一种回调函数。

    被观察者

    1. package com.example.listenertest;
    2. import java.util.ArrayList;
    3. import java.util.List;
    4. public class Subject {
    5. //观察者列表
    6. private List observerList = new ArrayList();
    7. //自身的一个状态变量
    8. private int state;
    9. //得到自身状态变量
    10. public int getState(){
    11. return state;
    12. }
    13. //设置自身状态变量
    14. public void setState(int state){
    15. this.state = state;
    16. //状态变量改变了,需要通知所有观察者
    17. notifyAllObservers();
    18. }
    19. //观察者通知方法
    20. public void notifyAllObservers(){
    21. //便利观察者列表
    22. for(Observer observer:observerList){
    23. //调用观察者的更新函数
    24. observer.update();
    25. }
    26. }
    27. //增加观察者
    28. public void attach(Observer observer){
    29. observerList.add(observer);
    30. }
    31. }

    可以看出,被观察者并不知道观察者具体是谁,也不依赖于观察者存在。

    被观察者只知道一个观察者队列,并且拥有将观察者加入到观察者队列的方法。

    当观察者在某个时机执行某个动作后,会对观察者队列里的所有的观察者进行通知,而通知的操作就是实现回调,调用观察者的回调函数,实现观察者的反馈机制。

    具体执行

    1. package com.example.listenertest;
    2. import android.util.Log;
    3. public class RedObserver extends Observer{
    4. //观察者是依赖于被观察者的,因此必须明确自己观察的是谁
    5. public RedObserver(Subject subject){
    6. this.subject = subject;
    7. this.subject.attach(this);
    8. }
    9. //实际上实现了一种回调机制,update就是回调函数
    10. @Override
    11. public void update() {
    12. Log.d("huankuai!","red subject state: "+this.subject.getState());
    13. }
    14. }

    以上是一种观察者,继承了观察者父类,实例化的时候可以自动将自己加入到被观察者中的观察者队列。

    1. protected void onCreate(Bundle savedInstanceState) {
    2. super.onCreate(savedInstanceState);
    3. setContentView(R.layout.activity_main);
    4. //实例化被观察者
    5. Subject mySubject = new Subject();
    6. //实例化两个观察者
    7. new RedObserver(mySubject);
    8. new BlueObserver(mySubject);
    9. //被观察者状态改变--20
    10. mySubject.setState(20);
    11. Log.d("huankuai!","state changed!--20");
    12. Toast.makeText(this,"state changed --20",Toast.LENGTH_SHORT).show();
    13. //被观察者状态改变--30
    14. mySubject.setState(30);
    15. Log.d("huankuai!", "state changed!--30");
    16. Toast.makeText(this,"state changed --30",Toast.LENGTH_SHORT).show();
    17. }

    实例化一个被观察者,两个观察者,当被观察在程序中改变状态时,调用观察者的回调函数,令观察者做出反馈。

    观察者解点耦合

    对具体的观察者可以改写一下,解除一点耦合,令观察者也可以只关心自己的动作与回调注册。

    1. package com.example.listenertest;
    2. public abstract class Observer {
    3. //添加被观察者的引用
    4. protected Subject subject;
    5. //更新的抽象方法
    6. public abstract void update();
    7. //监听被观察者
    8. public void addListener(Subject subject){
    9. this.subject = subject;
    10. subject.attach(this);
    11. }
    12. }

    以上可以看出,将监听被观察者的操作从具体的观察者类里转移到了抽象观察者类中。

    1. package com.example.listenertest;
    2. import android.util.Log;
    3. public class BlueObserver extends Observer{
    4. public BlueObserver(){}
    5. @Override
    6. public void update() {
    7. Log.d("huankuai!","blue subject state: "+ this.subject.getState());
    8. }
    9. }

    以上可见,具体观察者类里无须实现监听操作,甚至看不出这个类属于观察者模式。

    1. //实例化两个观察者
    2. RedObserver red = new RedObserver();
    3. BlueObserver blue = new BlueObserver();
    4. red.addListener(mySubject);
    5. blue.addListener(mySubject);

    当观察者实例化时,可以额外执行观察注册操作,代码更具有灵活性。

  • 相关阅读:
    python+django医院设备综合管理系统vue363
    【老生谈算法】matlab实现卡尔曼滤波算法源码——卡尔曼滤波
    Tomcat服务(部署、虚拟主机配置、优化)
    3月14日,每日信息差
    UE5.1_自定义配置文件读取
    向npm发包
    关于分布式一致性
    第十一章 : 如何使用Swagger2构建强大的API文档
    根目录挂载的/dev/mapper/centos-root分区扩容
    Maven多模块快速升级超好用Idea插件-MPVP
  • 原文地址:https://blog.csdn.net/m0_37872216/article/details/126274757