前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >观察者模式

观察者模式

作者头像
胖虎
发布2019-06-26 17:19:03
3250
发布2019-06-26 17:19:03
举报
文章被收录于专栏:晏霖晏霖

前言

观察者模式还算一个比较好玩的设计模式,其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。可以想象成消息中间件在系统中的作用。我认为观察者用的不是很多。

这是我最近阶段最后一次更新设计模式的文章了,我要去把精力放到其他地方,有感兴趣的小伙伴可以在下方留言,或者加公众号留言,我会回复你的,也可以直接在我的主页找微信二维码添加好友,让我们一同进步。

大家学过设计模式后要切记不是设计模式用的越多系统越好,不适合的不要强加过去,本来很简单的逻辑那么咱们就不要大费周折,设计模式的其中一点就是解决代码复用性,如果违背了就不好了。千万别拿着锤子看哪都像钉子啊,就好比学了分布式事务的解决方案就想在系统里应用,其实有的时候我们大可避免产生分布式事务的问题的,题外话题外话。

正文

概念:对象间的一对多的依赖关系。

网上这个概念说的太宽泛了。我找了一个图,请看

还有一个图,也可以帮助大家理解

观察者是一种面向接口编程

在观察者模式结构图中包含如下几个角色

● Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法notify()。目标类可以是接口,也可以是抽象类或具体类。 ● ConcreteSubject(具体目标):具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。 ● Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法collect(),因此又称为抽象观察者。 ● ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的collect()方法。

总之这些概念我是看的不舒服,看不懂没关系,我简单说一下吧。一共四个类。两个接口,两个接口实现类,

  • 被观察者方法参数引用的是观察者对象。
  • 观察者只定义一个自己的行为。
  • 具体观察者重写观察者的行为后还提供了构造方法为客户端调用。
  • 具体被观察者,这个类有些复杂,简单的说就是把外界消息通过该类的方法调用 notifyObserver()方法给提前准备好的Observer(观察者)接口中的方法去发送。

代码解释

Subject

代码语言:javascript
复制
public interface Subject {
    //添加观察者
    void addObserver(Observer o);

    //移除观察者
    void removeObserver(Observer o);

    //通知观察者方法
    void notifyObserver();
}

Observer

代码语言:javascript
复制
public interface Observer {    //观察者有只有收信息的行为
    void collect(String message);
}

具体观察者

代码语言:javascript
复制
public class User implements Observer {

    private String name;
    private String message;

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

    public void collect(String message) {
        this.message = message;
        read();
    }

    //观察者的实际行为
    public void read() {
        System.out.println(name + " 收到推送消息: " + message);
    }
}

具体被观察者

代码语言:javascript
复制
//被观察者的实现类,也就是微信公众号服务
public class WeChatServer implements Subject {
    //注意到这个List集合的泛型参数为Observer接口,设计原则:面向接口编程而不是面向实现编程
    private List<Observer> list = new ArrayList<Observer>();
    private String message;

    public void addObserver(Observer o) {
        list.add(o);
    }

    public void removeObserver(Observer o) {
        if (!list.isEmpty())
            list.remove(o);
    }

    //把消息发给每一个订阅的观察者
    public void notifyObserver() {
        for (int i = 0; i < list.size(); i++) {
            Observer observer = list.get(i);
            observer.collect(message);
        }
    }

    public void setInformation(String s) {
        this.message = s;
        System.out.println("微信服务更新消息: " + s);
        //消息更新,通知所有观察者
        notifyObserver();
    }
}

测试

代码语言:javascript
复制
public class ObserverTest {
    public static void main(String[] args) {
        WeChatServer server = new WeChatServer();

        Observer userA = new User("a");
        Observer userB = new User("b");
        Observer userC = new User("c");
        server.addObserver(userA);
        server.addObserver(userB);
        server.addObserver(userC);
        server.setInformation("PHP是世界上最好用的语言!");

        System.out.println("---------------------------");
        server.removeObserver(userA);
        server.setInformation("放屁,JAVA是世界上最好用的语言!");
    }
}

输出结果

在以下情况下可以考虑使用观察者模式: (1) 一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用。 (2) 一个对象的改变将导致一个或多个其他对象也发生改变,而并不知道具体有多少对象将发生改变,也不知道这些对象是谁。 (3) 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

比如有订阅性质的,发布性质的都可以使用。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 晏霖 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 正文
相关产品与服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档