Loading

设计模式——观察者模式

概念

观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

观察者模式结构图

该模式包含四个角色:

  • 抽象被观察者角色:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
  • 抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
  • 具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
  • 具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。

代码示例

下面用一个微信公众号发布文章的列子来简单讲解下观察者模式。通过这个列子,能帮助我们加深对观察者模式的理解。

step1:定义Subject和Observer接口

//定义一个微信公众号接口,相当于类图中的Subject角色
public interface WeChatOfficialAccount {

    public void registerObserver(WeChatObserver observer);
    public void removeObserver(WeChatObserver observer);
    public void notifyObserver(String message);

}
//定义一个微信用户接口,相当于类图中的Observer角色
public interface WeChatObserver {

    void pullArticle(String message);

}

step2:编写实现类

//这步没什么好说的
public class MyWeChatOfficialAccount implements WeChatOfficialAccount {

    private List<WeChatObserver> observerList;

    public MyWeChatOfficialAccount(){
        this.observerList = new ArrayList<>();
    }

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

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

    @Override
    public void notifyObserver(String message) {
        observerList.forEach(item->item.pullArticle(message));
    }
}

public class WeChatUser implements WeChatObserver {

    private String userName;

    public WeChatUser(String userName){
        this.userName = userName;
    }

    @Override
    public void pullArticle(String message) {
        System.out.println(userName+" receive message:"+message);
    }

}

step3:编写客户端类

public class Main {

    public static void main(String[] args) {
        WeChatUser user1 = new WeChatUser("csx-java");
        WeChatUser user2 = new WeChatUser("zr-php");

        WeChatOfficialAccount officialAccount = new MyWeChatOfficialAccount();
        //csx和zr两个用户都订阅了这个公众号
        officialAccount.registerObserver(user1);
        officialAccount.registerObserver(user2);

        //公众号发布文章,订阅者都会受到文章通知
        officialAccount.notifyObserver("Java is good...");
        //zr取消订阅
        officialAccount.removeObserver(user2);
        //再次发布文章
        officialAccount.notifyObserver("Java is more popular than php");
    }
}

优缺点

优点

  • 观察者和被观察者是抽象耦合的(面向接口耦合)。
  • 建立一套通知触发机制。

缺点

  • 如果需要通知的观察者太多,可能会比较耗时。其中一个观察者通知出问题的话可能会影响其他观察者的通知。

和生产者消费者模式的区别

这两种模式比较相似。其实我个人觉得没有太大的必须去纠结两者的区别。如果非要说下两者的区别的话,大概有:

  • 生产者模式中成产者一般不负责通知观察者,只是负责生产消息,然后将消息分发到一个消息队列。
  • 生产者消费者模式一般用于系统和系统之间解耦,而观察者模式一般用于系统内的某些逻辑。(可以参考Spring的ApplicationListener,这是一种金典的观察者模式的使用。)

参考

posted @ 2020-03-18 12:09  程序员自由之路  阅读(776)  评论(0编辑  收藏  举报