前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >观察者模式,从公众号群发说起

观察者模式,从公众号群发说起

原创
作者头像
平头哥的技术博文
修改于 2019-09-23 06:21:03
修改于 2019-09-23 06:21:03
4240
举报

每个人应该都订阅了不少微信公众号,那你有没有注意到微信公众号的消息呢?你订阅的公众号号主每发布一篇文章,你都会主动的接收到文章的推送,并不需要你点开每个订阅的公众号一一查看有没有更新,是不是觉得有点意思?感兴趣?那就接着往下看吧,因为接下来我们要模拟公众号群发的场景。

要模拟公众号群发,首先需要简单的了解一下公众号的特点,对于公众号的特点,我总结了以下三点:

  • 每个公众号会有多名订阅者,公众号跟订阅者在某种层面上是一对多的关系
  • 只有订阅者才能在公众号发布新文章时,会及时接收到推送通知,没有订阅公众号的阅读者不会接收到文章推送通知。
  • 每个订阅者都依赖于公众号号主,只有公众号号主发布文章,订阅者才有文章查看

现在业务场景我们大概知道了,那就开始动手编写我们的业务吧,我们先从公众号号主开始。

对于公众号号主,我们先理解一下公众号特点的第二点:只有订阅者才能在公众号发布新文章时,会及时接收到推送通知,没有订阅公众号的阅读者不会接收到文章推送通知。这个特点说明在公众号号主这边维护者订阅者的列表,在每次发布文章时会通知列表中的每一个订阅者告诉他们有新文章了。如果号主没有订阅者列表,那怎么知道需要通知哪些人呢?对于这个订阅者列表,号主肯定有增删的权利,毕竟这个公众号你说了算。根据上面分析的,我们给号主做出一个抽象,我们建立一个抽象的Author类。Author类具体设计如下:

代码语言:txt
AI代码解释
复制
/**
 * 号主抽象类
 */
public interface Author {
    // 添加关注者
    void addReader(Reader reader);
    // 删除关注者
    void deleteReader(Reader reader);
    // 通知关注者
    void notifyReader();
    // 写文章
    void writeArticle(String article);
}

在我们的场景中号主主要有添加订阅者、删除订阅者、通知订阅者和写文章的功能,号主有了,接下来就是我们的订阅者,订阅者在我们的场景中就比较简单了,只有一个阅读的功能,我们定义一个阅读者抽象类ReaderReader类的具体设计如下:

代码语言:txt
AI代码解释
复制
/**
 * 阅读者接口
 */
public interface Reader {
    // 阅读文章
    void reader(String authorName,String article);
}

号主和阅读者的接口都定义好了,下面我们就需要真正的号主和订阅者了。我们建立我们第一个号主平头哥PingtougeAuthorPingtougeAuthor类的设计如下:

代码语言:txt
AI代码解释
复制
/**
 * @author 平头哥
 * @title: PingtougeAuthor
 * @projectName observer
 * @description: 号主平头哥
 * @date 2019/9/1817:50
 */
public class PingtougeAuthor implements Author{
    // 订阅者列表
    private Vector<Reader> readers ;
    // 作者名称
    private String name;
    // 文章
    private String article;

    public PingtougeAuthor(String name){
        this.name = name;
        this.readers = new Vector<>();
    }
    /**
     * 添加关注者
     * @param reader
     */
    @Override
    public void addReader(Reader reader) {
        if (readers.contains(reader)) return;
        readers.add(reader);
    }
    /**
     * 移除关注者
     * @param reader
     */
    @Override
    public void deleteReader(Reader reader) {
        readers.remove(reader);
    }
    /**
     * 通知关注者
     */
    @Override
    public void notifyReader() {
        for (Reader reader:readers){
            reader.reader(name,article);
        }
    }
    /**
     * 写文章
     * @param article
     */
    @Override
    public void writeArticle(String article){
        this.article = article;
        notifyReader();
    }
}

我们在建立王山、张三、李四三个订阅者,他们的具体设计如下:

代码语言:txt
AI代码解释
复制
/**
 * 订阅者王山
 */
public class WangSanReader implements Reader{
    private String name;
    public WangSanReader(String name){
        this.name = name;
    }
    @Override
    public void reader(String authorName,String article) {
        System.out.println(name+" 阅读了 "+authorName+" 发布的 "+article+" 文章");
    }
}
代码语言:txt
AI代码解释
复制
/**
 * 订阅者张三
 */
public class ZhangsanReader implements Reader{
    private String name;

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

    @Override
    public void reader(String authorName,String article) {
        System.out.println(name+" 阅读了 "+authorName+" 发布的 "+article+" 文章");
    }
}
代码语言:txt
AI代码解释
复制
/**
 * 订阅者者李四
 */
public class LiSiReader implements Reader{
    private String name;

    public LiSiReader(String name){
        this.name = name;
    }
    @Override
    public void reader(String authorName,String article) {
        System.out.println(name+" 阅读了 "+authorName+" 发布的 "+article+" 文章");
    }
}

号主和订阅者都有了,万事俱备只欠东风,那我们就来进行我们第一次场景模拟,在这次模拟中,订阅者张三、王山订阅了平头哥的公众号,李四没有订阅平头哥的公众号。按照我们的设想平头哥发布文章时,张三、王山可以接收到文章推送通知,李四不会接收到文章推送通知。编写我们的第一个模拟类:

代码语言:txt
AI代码解释
复制
public class App {
    public static void main(String[] args) {
        PingtougeAuthor pingtougeAuthor = new PingtougeAuthor("平头哥");
        
        WangSanReader wangSanReader = new WangSanReader("王山");
        ZhangsanReader zhangsanReader = new ZhangsanReader("张三");
        LiSiReader liSiReader = new LiSiReader("李四");
        
        // 王山订阅了平头哥的公众号
        pingtougeAuthor.addReader(wangSanReader);
        // 张三订阅了平头哥的公众号
        pingtougeAuthor.addReader(zhangsanReader);
        
        pingtougeAuthor.writeArticle("看完这篇你还不知道这些队列,我这些图白作了");
    }
}

测试结果:

2019-09-18 20-05-03屏幕截图.png
2019-09-18 20-05-03屏幕截图.png

从测试结果中,我们可以看出张三、王山接收到了平头哥发布文章的推送通知,李四没有接收到,符合我们的预期。

接下来我们进行第二次模拟,由于平头哥最近发了不少干货,李四决定也关注平头哥的公众号,所以我们对模拟类进行了修改,修改后的模拟类如下:

代码语言:txt
AI代码解释
复制
public class App {
    public static void main(String[] args) {
        PingtougeAuthor pingtougeAuthor = new PingtougeAuthor("平头哥");
        WangSanReader wangSanReader = new WangSanReader("王山");
        ZhangsanReader zhangsanReader = new ZhangsanReader("张三");
        LiSiReader liSiReader = new LiSiReader("李四");

        // 王山订阅了平头哥的公众号
        pingtougeAuthor.addReader(wangSanReader);
        // 张三订阅了平头哥的公众号
        pingtougeAuthor.addReader(zhangsanReader);
//
//        pingtougeAuthor.writeArticle("看完这篇你还不知道这些队列,我这些图白作了");
        // 李四也订阅平头哥的公众号
        pingtougeAuthor.addReader(liSiReader);

        pingtougeAuthor.writeArticle("实现 Java 本地缓存,该从这几点开始");

    }
}

测试结果:

2019-09-18 20-12-56屏幕截图.png
2019-09-18 20-12-56屏幕截图.png

这次三个订阅者都接收到了平头哥发布文章的推送通知。关注了平头哥的公众号有一段时间后,张三觉得平头哥的公众号不适合自己,于是就取关了平头哥的公众号,这是我们要模拟的第三个场景,我们对模拟类进行修改,修改后的模拟类如下:

代码语言:txt
AI代码解释
复制
public class App {
    public static void main(String[] args) {
        PingtougeAuthor pingtougeAuthor = new PingtougeAuthor("平头哥");
        WangSanReader wangSanReader = new WangSanReader("王山");
        ZhangsanReader zhangsanReader = new ZhangsanReader("张三");
        LiSiReader liSiReader = new LiSiReader("李四");

        // 王山订阅了平头哥的公众号
        pingtougeAuthor.addReader(wangSanReader);
        // 张三订了平头哥的公众号
        pingtougeAuthor.addReader(zhangsanReader);
//
//        pingtougeAuthor.writeArticle("看完这篇你还不知道这些队列,我这些图白作了");

        // 李四订了平头哥的公众号
        pingtougeAuthor.addReader(liSiReader);

//        pingtougeAuthor.writeArticle("实现 Java 本地缓存,该从这几点开始");
        // 张三取关了平头哥的公众号
        pingtougeAuthor.deleteReader(zhangsanReader);
        pingtougeAuthor.writeArticle("实观察者模式,从微信公众号说起");

    }
}

测试结果:

2019-09-18 20-21-20屏幕截图.png
2019-09-18 20-21-20屏幕截图.png

张三取关之后,平头哥发布的文章,他将不会再接收到推送通知。在上面公众号群发的模拟场景中,我们使用到了一种设计模式,叫做观察者模式,那今天我们就一起来简单的了解一下观察者模式。

观察者模式定义

观察者模式又叫发布-订阅模式,发布-订阅模式大家应该非常熟悉了吧,消息中间件就是发布-订阅模式,观察者模式主要也是应用在消息中间件。观察者模式定义了一种一对多的依赖关系让多个订阅者同时监听某一个对象主题,这个主题对象在状态发生变化时,会通知所有的订阅者,让他们自己更新自己。这些特点在我们的模拟场景中基本上都体现出来了,如果你对这些有疑问,可以多看我们的模拟场景。

观察者的结构

  • 抽象主题(Subject)角色:抽取出了主题所需要定义的接口,比如我们的Author
  • 具体主题(Concrete Subject)角色:具体的主题实现者,该类必须继承抽象主题,比如我们的PingtougeAuthor
  • 抽象观察者(Observer)角色:观察者抽象类,定义观察者需要的接口,比如我们的Reader
  • 具体观察者(Concrete Observer)角色:具体的观察者,做这具体业务的类,比如我们的三个订阅者

观察者的 UML 图

3-1Q1161A6221S.gif
3-1Q1161A6221S.gif

观察者模式的优点

  • 主题与观察者之间松耦合
  • 支撑广播通信:一条消息可以通知给多个人
  • 建立一条触发链:A触发B,B触发C,一条触发链,不过这个需要注意的地方很多

观察者的缺点

  • 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率
  • 如果采用顺序通知,当某个观察者卡住了,其他的观察者将无法接收到通知
  • 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃

观察者模式差不多就这些内容,相对来说比较容易理解,另外多说一句,在JDK中已经内置了观察者模式,在java.util下的ObservableObserver两个类,有兴趣的可以去了解一下。

源代码

文章不足之处,望大家多多指点,共同学习,共同进步

原文发布于微信公众号 - 平头哥的技术博文(z694644032)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
订阅发布模式到底是不是观察者模式?
快手前天发布了《看见》一时间好评如潮,盖过了之前的《后浪》。现如今搞内容创作都要开始玩价值观导向了。不过互联网真是一个神奇的东西,我们足不出户就可以看到你想看的东西。不管是时下火热的抖音、快手,还是微信公众号、知乎。你只需要关注订阅你喜欢的领域,你就可以获取你想要的内容,甚至和创作者进行互动。创作者只需要创作的内容发布到对应的平台上,用户只需要在对应的平台上订阅自己喜欢的领域或者作者就可以了。用户和创作者并不认识,但是他们却可以“看见”。从编程范式上来说这就是发布-订阅。
码农小胖哥
2020/06/11
1.3K0
订阅发布模式到底是不是观察者模式?
Go 设计模式-观察者模式
观察者模式,也被称为发布订阅模式(Publish-Subscribe Design Pattern)
王小明_HIT
2021/07/27
3970
php设计模式(十九):观察者模式(Observer)
观察者模式又称为:事件订阅者、监听者、Event-Subscriber、Listener、Observer。观察者是一种行为设计模式,允许定义一种订阅机制,可在对象事件发生时通知多个“观察”该对象的其他对象。
高久峰
2023/09/18
1470
php设计模式(十九):观察者模式(Observer)
【愚公系列】2021年12月 二十三种设计模式(十九)-观察者模式(Observer Pattern)
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。
愚公搬代码
2022/12/01
3050
【愚公系列】2021年12月 二十三种设计模式(十九)-观察者模式(Observer Pattern)
Java设计模式-观察者模式(订阅发布模式)
在现实世界中,许多对象并不是独立存在的,其中一个对象的行为发生改变可能会导致一个或者多个其他对象的行为也发生改变。
宁在春
2022/10/31
1.1K0
Java设计模式-观察者模式(订阅发布模式)
设计模式之观察者模式及典型应用
微信公众号有服务号、订阅号和企业号之分。以我的公众号为例,我的公众号类型是订阅号,名称是 "小旋锋",专注于大数据,Java后端类技术分享。目前主要是分享学习笔记为主,尽量做到 "原创"、"高质量"、"成体系"。每当我发布一篇博文推送,订阅的用户都能够在我发布推送之后及时接收到推送,即可方便地在手机端进行阅读。
小旋锋
2019/01/21
1.1K0
设计模式---观察者模式
微信公众号有服务号、订阅号和企业号之分。当我们在公众号上发布一篇博文推送时,订阅的用户都能够在我发布推送之后及时接收到推送,即可方便地在手机端进行阅读。
大忽悠爱学习
2021/11/15
2680
观察者模式(Observer)
1. 问题场景 当一个对象的状态放生改变的时候,如何让依赖于它的所有对象得到通知,并进行相应的处理? 2. UML图 Subject:目标对象,通常具有以下功能 一个目标对象可以被多个观察者观察 目标
Java高级架构
2018/07/20
4810
设计模式-观察者模式
JDK中也有自带的观察者模式。但是被观察者是一个类而不是接口,限制了它的复用能力。
Anymarvel
2018/10/22
3550
设计模式-观察者模式
观察者模式
观察者模式需要如下几个对象构建出整个框架: 1抽象主题角色:提供了一个用于保存观察者对象的聚集类和增加删除观察者对象的方法,以及通知所有观察者的抽象方法 2具体主题:具体目标类,实现抽象主题的类 3抽象观察者:是一个抽象类接口,包含一个更新自己的抽象方法,更改通知时随时被调用 4具体观察者
gzq大数据
2022/05/11
3860
设计模式之观察者模式:实现松耦合通信
在现实世界中,许多对象都不是独立存在的。其中一个对象的行为发生改变可能会导致一个或者多个其他对象的行为也发生改变。
程序视点
2023/09/13
2550
设计模式之观察者模式:实现松耦合通信
CRUD很无聊?一起学设计模式吧!— 观察者模式
观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
JAVA日知录
2019/10/19
6520
CRUD很无聊?一起学设计模式吧!— 观察者模式
观察者模式
观察者模式 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象,当主题对象在状态上发生改变时,通知所有的观察者对象,并让他们自动更新自己; 观察者模式的组成 抽象主题角色: 将所有的观察者引用存放到一个集合中,每个主题可以拥有任意数量的观察者;主题提供一个接口,用来增加,移除通知观察者。一般用一个抽象类或接口来实现; 抽象观察者角色: 为所有的观察者定义一个接口,在得到主题通知时更新自己; 具体主题角色: 在具体主题状态发生改变时,通知所有登记过的观察者。具体主题通常由一个子类实现
佛系编码
2018/05/22
4420
设计模式-观察者模式
自从有了微信公众号后,关注了某个公众号基本每天都有新的文章推送的通知,我们可以很方便的进行查阅,了解最新的资讯,什么老美放大水、什么中东又暴乱了,第一时间就知道了,而这里的关注和通知的行为其实有点类似观察者模式的观察者。用户关注公众号,公众号(被观察者)更新文章通知所有用户(观察者)。
逍遥壮士
2020/09/18
3780
浅谈几种设计模式--观察者模式
1 定义:在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。
田维常
2019/07/16
4070
浅谈几种设计模式--观察者模式
五分钟学会观察者模式
观察者模式:多个观察者同时监听一个主题对象,当主题对象发生改变时,它的所有观察者都会收到通知。
Java识堂
2020/03/25
3840
五分钟学会观察者模式
观察者模式
观察者模式还算一个比较好玩的设计模式,其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。可以想象成消息中间件在系统中的作用。我认为观察者用的不是很多。
胖虎
2019/06/26
3600
观察者模式
通俗易懂设计模式解析——观察者模式
  今天我们一起看看这个观察者模式,这个模式简单来说就是一个发布订阅类似的模式。按照名字来理解也就是存在一个观察者和一个被观察者。说几个例子给大家听,大家应该就明白了。例如在我们现在通过银行卡支付之后,会收到银行发过来的提示信息。例如当我们话费余额或者流量不足之时也会收到提示信息。这其中的逻辑帮我们理解观察者模式。当我们观察的一个对象发送变化之时就会触发某一机制。然后做出一系列的措施。
小世界的野孩子
2019/10/11
4520
通俗易懂设计模式解析——观察者模式
java设计模式-观察者模式
模式定义 定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。主题(Subject)是被观察的对象,而其所有依赖者(Observer)称为观察者。 设计原则 为交
三哥
2018/06/15
6790
观察者模式(设计模式)
观察者模式其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。可以想象成消息中间件在系统中的作用。SpringBoot启动就是使用了观察者模式。
WindSun
2019/09/10
5970
观察者模式(设计模式)
推荐阅读
相关推荐
订阅发布模式到底是不是观察者模式?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档