扫码关注微信公众号

回复“面试手册”,获取本站PDF版

回复“简历”,获取高质量简历模板

回复“加群”,加入程序员交流群

回复“电子书”,获取程序员类电子书

当前位置: 计算机基础 > 设计模式 > 观察者模式

这是设计模式的第四篇,前面介绍了单例模式、代理模式、工厂模式,今天来介绍下观察者模式

观察者模式相比于前面介绍的几种模式会简单些,篇幅也会短很多

观察者模式听起来比较抽象,如果叫订阅-发布模式,很多人一下子就能理解了,主要目的就是解耦

观察者模式定义了一种一对多的关系,可以多个观察者对象同时监听某一个主题对象,当主题对象在状态变化时,会通知所有的观察者对象。就像有一些读者关注我的公众号,当我发表了文章,关注我公众号的读者就可以看到。

在观察者模式中,主要有以下几种角色

  • Subject:抽象主题,抽象主题提供一个接口,可以增加和删除观察者对象
  • ConcreteSubject:具体主题,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知(发布通知)
  • Observer:抽象观察者,定义了一个更新接口,使得在得到主题更改通知时更新自己
  • ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在收到主题更改通知时更新自身的状态(收到通知,可以有多个具体观察者)

类图如下:

观察者模式
观察者模式

将具体的主题举例为公众号,具体的观察者为工具人张三、李四、王五

具体的实现代码如下:

抽象主题(Subject)

public interface Subject {
    /**
     * 增加订阅者
     * @param observer
     */
    public void attach(Observer observer);
    /**
     * 删除订阅者
     * @param observer
     */
    public void detach(Observer observer);
    /**
     * 通知订阅者更新消息
     */
    public void notify(String message);
}

具体主题(ConcreteSubject),这里用我的公众号路人zhang来举例,一般情况最好不要用中文命名,虽然不会报错

public class 路人zhang implements Subject {
    //储存订阅公众号的读者
    private List<Observer> ReaderList = new ArrayList<Observer>();

    @Override
    public void attach(Observer observer) {
        ReaderList.add(observer);
    }

    @Override
    public void detach(Observer observer) {
        ReaderList.remove(observer);
    }

    @Override
    public void notify(String message) {
        for (Observer observer : ReaderList) {
            observer.update(message);
        }
    }
}

抽象观察者(Observer)

public interface Observer {
    public void update(String message);
}

具体观察者(ConcrereObserver),这里以公众号的读者为例,忠实读者,张三、李四、王五

public class Reader implements Observer {

    private String name;
    public Reader(String name) {
        this.name = name;
    }
    @Override
    public void update(String message) {
        System.out.println( message + "-" + name + "拿到了offer");
    }
}

测试一下

class Client {
    public static void main(String[] args) {
        路人zhang LuRenZhang = new 路人zhang();
        //创建微信用户
        Reader user1=new Reader("张三");
        Reader user2=new Reader("李四");
        Reader user3=new Reader("王五");
        //订阅公众号
        LuRenZhang.attach(user1);
        LuRenZhang.attach(user2);
        LuRenZhang.attach(user3);
        //公众号更新发出消息给订阅的读者
        LuRenZhang.notify("看完了路人zhang的面试手册");
    }
}

结果是看了路人zhang面试手册的都拿到offer,没看的估计够呛了(疯狂暗示)

看完了路人zhang的面试手册-张三拿到了offer
看完了路人zhang的面试手册-李四拿到了offer
看完了路人zhang的面试手册-王五拿到了offer

观察者模式的优点:解耦,观察者和被观察者是抽象耦合的

观察者模式的缺点:

  • 如果存在多个观察者,更新时通知多个观察者会花费较多时间,并且如果是顺序执行,一个观察者卡住,会导致整个系统卡住
  • 如果观察者和被观察者之间存在循环依赖,可能会导致循环调用,使得系统崩溃

观察者模式的应用场景:关联行为之间建立一套触发机制的场景,例如关注的微博的通知等


点击面试手册,获取本站面试手册PDF完整版