观察者模式(Observer)

232 阅读2分钟

定义

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

本质

触发联动

登场角色

  • Subject(观察对象)

    被观察对象接口或者抽象类

  • ConcreteSubject(具体的观察对象)

    具体的被观察对象

  • Observer(观察者)

    负责接收来自观察对象的状态变化的通知

  • ConcreteObserve(具体的观察者)

    具体的观察者,实现观察者角色所定义的接口。

示例代码

/**
 * 观察者
 */
public class Coder implements Observer {
    String name;

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

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("Hi, " + name + " DevTechFrontier更新了" + arg);
    }

    @Override
    public String toString() {
        return "Coder{" +
                "name='" + name + '\'' +
                '}';
    }
}



/**
 * 被观察者
 */
public class DevTechFronter extends Observable {
    public void postNewContent(String content){
        //标志内容发生改变
        setChanged();
        //通知所有观察者
        notifyObservers(content);
    }
}


public class Client {
    public static void main(String[] args){
        //被观察的角色
        DevTechFronter devTechFronter = new DevTechFronter();
        //观察者
        Coder coder1 = new Coder("Coder1");
        Coder coder2 = new Coder("Coder2");
        Coder coder3 = new Coder("Coder3");
        //将观察者注册到被观察者列表中
        devTechFronter.addObserver(coder1);
        devTechFronter.addObserver(coder2);
        devTechFronter.addObserver(coder3);
        //发布消息
        devTechFronter.postNewContent("this is the new content.");
    }
}

运行结果

Hi, Coder3 DevTechFrontier更新了this is the new content.
Hi, Coder2 DevTechFrontier更新了this is the new content.
Hi, Coder1 DevTechFrontier更新了this is the new content.

优点

  • 观察者模式实现了观察者和目标之间的抽象耦合,原本目标对象发生变化时,需要直接调用所有的观察者对象,但是抽象出观察者接口后,目标和观察者就在抽象层面上耦合和,也就是目标只知道观察者接口,并不知道具体的观察者的类,从而实现了目标类和观察者之前的耦合。
  • 观察者模式实现了动态联动。所谓联动,就是一个操作会引起其他相关的操作。

缺点

  • 可能会引起无谓的操作。 由于观察者模式每次都是广播通信,不管观察者是否需要,每个观察者都会被调用update方法。

使用场景

  • 当一个抽象模型有两个方面,一个方面的操作依赖于另一个方面的状态变化时,就可以选用观察者模式,将这两种封装成观察者和目标对象。
  • 如果在更改一个对象的时候,同时需要连带改变其他的对象。
  • 当一个对象必须通知其他对象,但是又希望这个对象和其他被通知的对象松散耦合的时候。