Java设计模式 - 观察者模式

定义

  • 观察者 Observer,也称订阅者 Subscriber
  • 被观察者 Observable,也称主题 Subject

定义对象间(被观察者和观察者)一种一对多的依赖关系,使得每当一个对象(被观察者)改变状态时,则所有依赖于它的对象(观察者)都能得到通知并被自动更新。类似于发布/订阅模式,Observer订阅主题,Observable则负责发布内容,从而将二者联系起来。

使用场景

  • 用于解决解耦问题,观察者和被观察者高度分离,只依赖于ObserverObservable抽象;
  • 关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系;
  • 事件多级触发场景;
  • 跨系统消息交换场景,如消息队列,事件总线的处理机制。

Andorid源码实例

  • ListView适配器AdapternotifyDataSetChanged()方法,在方法中遍历所有的观察者,回调其onChanger()方法;
  • BroadcastReceiver的注册与触发,通过Context.registerReceiver()方法将BroadcastReceiver(相当于观察者)注册到AMS中,当通过sendBroadcast()发送广播时(相当于主题数据发生变更),所有注册了对应IntentFilter actionBroadcastReceiver将会被执行;
  • EventBus消息总线
  • java.util包中也有ObservableObserver的默认实现,可参考使用

UML类图

image-20200502000759111.png

代码示例

首先定义抽象观察者,观察者只关心主题的变更

public interface Observer {

    /**
     * 处理数据更新的方法(在主题发生变更时由主题主动触发)
     *
     * @param message 变更的数据部分
     */
    void update(String message);

}

接着定义抽象主题(作为被观察者,也有命名为Observable),主题是供观察者观察的对象

public interface Subject {

    /**
     * 订阅操作
     * @param observer 观察者
     */
    void registerObserver(Observer observer);

    /**
     * 取消订阅操作
     * @param observer 观察者
     */
    void removeObserver(Observer observer);

    /**
     * 通知变动
     */
    void notifyChanged();

}

接着实现观察者,对主题变更作具体处理

public class Subscriber implements Observer {

    private String name;
    private String message;

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

    @Override
    public void update(String message) {
        this.message = message;
        read();
    }

    private void read() {
        System.out.println(name + " 收到新消息: " + message);
    }
}

最后再实现主题

public class Publisher implements Subject {

    private String message;

    private List observerList = new ArrayList<>();

    @Override
    public void registerObserver(Observer observer) {
        observerList.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyChanged() {
        for (Observer observer : observerList) {
            observer.update(message);
        }
    }

    public void pushMessage(String message) {
        this.message = message;
        System.out.println("出版社发布新消息: " + message);
        // 推送消息
        notifyChanged();
    }
}

作如下测试:

public class Test {

    public static void main(String[] args) {

        Subscriber john = new Subscriber("John");
        Subscriber jack = new Subscriber("jack");
        Subscriber tom = new Subscriber("tom");

        Publisher publisher = new Publisher();
        publisher.registerObserver(john);
        publisher.registerObserver(jack);
        publisher.registerObserver(tom);

        publisher.pushMessage("Today is Monday");
        publisher.removeObserver(jack);
        publisher.pushMessage("Today is Tuesday");
    }
}

输出结果如下:

出版社发布新消息: Today is Monday
John 收到新消息: Today is Monday
jack 收到新消息: Today is Monday
tom 收到新消息: Today is Monday
出版社发布新消息: Today is Tuesday
John 收到新消息: Today is Tuesday
tom 收到新消息: Today is Tuesday

优点

  • 观察者和被观察者之间是抽象耦合,可灵活应对业务变化;
  • 增强系统灵活性,可扩展性。

缺点

  • 运用时需要考虑开发效率和运行效率问题,程序中包括一个被观察者、多个观察者、开发和调试等内容会比较复杂;
  • 在Java中消息的通知默认是顺序执行,一个观察者卡顿,会影响其他观察者的执行,所以通常情况下会采用异步的方式实现update()方法

你可能感兴趣的:(Java设计模式 - 观察者模式)