观察者模式初学

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013483704/article/details/88671702

观察者模式

定义很简单,观察者模式是关于多个对象想知道一个对象中数据变化情况的一种成熟的模式。
观察者模式中有一个称作“主题”的对象和若干个称作“观察者”的对象,“主题”和“观察者”间是一种一对多的依赖关系,当“主题”的状态发生变化时,所有“观察者”都得到通知。即一个对象被修改时,则会自动通知它的依赖对象。

使用场景

  1. 一个对象的数据更新时需要通知其他对象,但这个对象又不希望和被通知的那些对象形成紧耦合。

  2. 一个对象的数据更新时,这个对象需要让其他对象也各自更新自己的数据,但这个对象不知道具体有多少对象需要更新数据。

结构框架

借用网上一张图,
在这里插入图片描述

观察者模式实现时的结构框架基本如上图所示,分为四个部分:

  1. 主题(Subject):主题是一个接口(也可以是类,java内置的观察者模式就是用的类observable,但没有接口好用),该接口规定了具体主题需要实现的方法,比如,添加、删除观察者以及通知观察者更新数据的方法,对于添加和删除等操作,需要具体的知道是哪个观察者,所以相应的接口中也就需要有一个观察者observer作为参数。

  2. 观察者(Observer):观察者是一个接口,该接口规定了具体观察者用来更新数据的方法,为了松耦合,接口是很好的选择,但看实现的话,也是可以用类的吧。

  3. 具体主题(ConcreteSubject):具体主题是实现主题接口类的一个实例,该实例包含有可以经常发生变化的数据。具体主题需使用一个集合,比如ArrayList,存放观察者的引用,以便数据变化时通知具体观察者。

  4. 具体观察者(ConcreteObserver):具体观察者是实现观察者接口类的一个实例。具体观察者包含有可以存放具体主题引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,使自己成为它的观察者,或让这个具体主题将自己从具体主题的集合中删除,使自己不再是它的观察者。

使用方法

  1. 定义抽象观察者接口
public interface Observer {

    public void update(String msg, TextView text);
}
  1. 实现观察者接口
public class UserAccount implements Observer {

    private String name;

    public UserAccount(String name) {
        this.name = name;
    }

    @Override
    public void update(String msg, TextView text) {
        text.setText(text.getText() + name + ":" + msg + "\n");
    }
}
  1. 定义抽象被观察者,即主题接口
public interface Subject {
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObserver(String msg, TextView text);
}
  1. 实现主题接口
public class PersonSubject implements Subject {

    //存放观察者的引用
    private List<Observer> mPersonList = new ArrayList<>();

    @Override
    public void registerObserver(Observer o) {
        mPersonList.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        mPersonList.remove(o);
    }

    @Override
    public void notifyObserver(String msg, TextView text) {
    //数据变化时通知具体观察者,所以需要循环去调用集合(比如ArrayList)中存放观察者的引用,从而调用到各个观察者的update方法
        for (Observer observer : mPersonList) {
            observer.update(msg, text);
        }
    }
}

完成以上四步,就可以编写实际使用的客户端类了,具体可见code。

与回调的区别

个人理解来看,回调也可以看作是一类比较特殊的观察者模式。

回调函数的实现如下:

//定义抽象观察者接口
public interface Callback {
   void onCall();
}

//实现具体主题接口
public class A {  
    private CallBack callback;  
    //注册一个事件  
    public void register(CallBack callback){  
        this.callback = callback;  
    }  
    // 需要调用的时候回调  
    public void call(){  
        callback.oncall();  
    }  
} 

public static void main(String[] args) {  
    A a = new A();  
    a.register(new CallBack() {  //这里new 了一个callback,实际上可以看成是实现具体观察者类接口
        @Override  
        public void oncall() {  
            System.out.println("回调函数被调用");  
        }  
    });  
    a.call();  //最后实际调用
}

综上来看,回调机制和观察者模式是一致的,区别是观察者模式里面目标类维护了所有观察者的引用,而回调里面只是维护了一个引用。

猜你喜欢

转载自blog.csdn.net/u013483704/article/details/88671702