设计模式-观察者模式(Observer Pattern)

847 阅读4分钟

Github 源码地址

23种设计模式总览

创建型模式

结构型模式

行为型模式

定义

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

优缺点

优点:  1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。

缺点:  1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

实现

观察者模式主要由以下四个角色组成

  • subject:它是抽象主题的接口,对象通过此接口将自己注册为观察者,或将自己从观察中者删除

  • ConcreteSubject:一个实现主题接口的具体主题,除了实现添加和删除的方法外,它还有一个update方法,用来在状态改变时通知所有观察者

  • Observer:观察者接口,所有具体的观察者都实现此接口

  • ConcreteObserver:具体的观察者

//观察者接口
public interface Observer {
    // 处理业务逻辑
    void update(String message);
}
//具体的观察者
class ConcreteObserver implements Observer {
    String name;

    //此处只想验证多个观察者 只是添加了名字区分一下
    public ConcreteObserver(String name) {
        this.name = name;
    }

    @Override
    public void update(String message) {
        // 模拟处理业务逻辑
        System.out.println(name + " 知道了你更新了" + message);
    }
}
//抽象主题的接口
public interface Subject {
    // 添加订阅关系
    void addObserver(Observer observer);

    // 移除订阅关系
    void removeObserver(Observer observer);

    // 通知订阅者
    void notifyObservers(String message);
}
//具体主题
public class ConcreteSubject implements Subject {

    // 订阅者容器
    private List<Observer> observers = new ArrayList<Observer>();

    @Override
    public void addObserver(Observer observer) {
        // 添加订阅关系
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        // 移除订阅关系
        observers.remove(observer);
    }

    @Override
    public void notifyObservers(String message) {
        // 通知订阅者们
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

验证

class Test {
    public static void main(String[] args) {

        ConcreteSubject subject = new ConcreteSubject();
        // 这里添加2个观察者
        ConcreteObserver concreteObserver1 = new ConcreteObserver("观察者1");
        subject.addObserver(concreteObserver1);
        subject.addObserver(new ConcreteObserver("观察者2"));

        //通知观察者更新数据
        subject.notifyObservers("第一次");
        //输出结果:
        //观察者1 知道了你更新了第一次
        //观察者2 知道了你更新了第一次

        // 删除第一个观察者测试
        subject.removeObserver(concreteObserver1);
        //通知观察者更新数据(只有观察者2才会收到更新内容)
        subject.notifyObservers("第二次");
        // 输出结果:
        //观察者2 知道了你更新了第二次
    }
}