在公司开发项目,如果碰到一些在特定条件下触发某些逻辑操作的功能的实现基本上都是用的定时器

比如用户注册完后,发送邮件,为了防止邮件发送失败或者发送邮件比较耗时,一般也都是通过定时器去扫库里注册没有发邮件的用户数据

再比如一个订单,在改变状态后,要归档,这也是通过定时器来实现的,扫描订单的数据,通过判断状态来做相对应的处理

但这样处理的话,定时器就会越来越多,总觉得不太好

然后,从一些资讯网站上的订阅功能想到了是否可以使用java里的观察者模式来解决这个问题,比如定单的状态改变了,这是一个主题,直接通知订阅这个主题的实现类来处理这个订单,这样不是更方便吗,于是从观察者模式入手,折腾了一下

创建主题(Subject)接口

定义主题的接口

package co.yiiu;

/**
* Created by tomoya at 2019/4/8
*/
public interface Subject { // 设置主题内容
void setContent(String content); // 获取主题内容
String getContent(); // 添加订阅者
void attach(Observer observer); // 删除订阅者
void detach(Observer observer); // 发布消息
void publish();
}

创建订阅者(Observer)接口

package co.yiiu;

/**
* Created by tomoya at 2019/4/8
*/
public interface Observer { // 订阅主题
void subscribe(Subject subject); // 取消订阅
void unsubscribe(Subject subject); // 处理订阅的消息
void update(Subject subject);
}

原链文接:https://tomoya92.github.io/2019/04/08/java-subscribe-publish/

实现主题

我这里实现了两个主题

  • NewsSubject 新闻主题,订阅了这个主题的观察者可以获取这个主题更新的新闻内容
  • WeatherSubject 天气主题,订阅了这个主题的观察者可以获取这个主题发布的天气情况

具体代码如下

package co.yiiu;

import java.util.ArrayList;
import java.util.List; /**
* Created by tomoya at 2019/4/8
*/
public class NewsSubject implements Subject { private String content;
private List<Observer> observers = new ArrayList<>(); @Override
public String getContent() {
return content;
} @Override
public void setContent(String content) {
this.content = content;
} // 添加观察者
@Override
public void attach(Observer observer) {
observers.add(observer);
} // 删除观察者
@Override
public void detach(Observer observer) {
observers.remove(observer);
} // 通知观察者
@Override
public void publish() {
observers.forEach(observer -> observer.update(this));
}
}
package co.yiiu;

import java.util.ArrayList;
import java.util.List; /**
* Created by tomoya at 2019/4/8
*/
public class WeatherSubject implements Subject { private String content;
private List<Observer> observers = new ArrayList<>(); @Override
public String getContent() {
return content;
} @Override
public void setContent(String content) {
this.content = co 大专栏  Java里观察者模式(订阅发布模式)ntent;
} @Override
public void attach(Observer observer) {
observers.add(observer);
} @Override
public void detach(Observer observer) {
observers.remove(observer);
} @Override
public void publish() {
observers.forEach(observer -> observer.update(this));
}
}

文原链接:https://tomoya92.github.io/2019/04/08/java-subscribe-publish/

实现观察者

我这写了一个通用的实现,创建观察者的时候,传递一个名字表示不同的观察者

package co.yiiu;

/**
* Created by tomoya at 2019/4/8
*/
public class ConcreteObserver implements Observer { private String name; public ConcreteObserver(String name) {
this.name = name;
} @Override
public void subscribe(Subject subject) {
subject.attach(this);
} @Override
public void unsubscribe(Subject subject) {
subject.detach(this);
} @Override
public void update(Subject subject) {
System.out.println(this.name + " 订阅的内容: " + subject.getContent());
}
}

测试

package co.yiiu;

import org.junit.Test;

/**
* Created by tomoya at 2019/4/8
*/
public class TestObserver { @Test
public void test() {
// 创建主题对象
Subject newsSubject = new NewsSubject();
Subject weatherSubject = new WeatherSubject(); // 给主题赋值
newsSubject.setContent("我是一条新闻消息");
weatherSubject.setContent("我是一条天气消息"); // 创建订阅者
Observer concreteObserver1 = new ConcreteObserver("用户1");
// 订阅newsSubject
concreteObserver1.subscribe(newsSubject); Observer concreteObserver2 = new ConcreteObserver("用户2");
// 订阅newsSubject和weatherSubject
concreteObserver2.subscribe(newsSubject);
concreteObserver2.subscribe(weatherSubject); Observer concreteObserver3 = new ConcreteObserver("用户3");
// 订阅weatherSubject
concreteObserver3.subscribe(newsSubject);
concreteObserver3.subscribe(weatherSubject); // user2 取消订阅newsSubject
concreteObserver2.unsubscribe(newsSubject); // 发布消息
newsSubject.publish();
weatherSubject.publish(); }
}

运行结果

用户1 订阅的内容: 我是一条新闻消息
用户3 订阅的内容: 我是一条新闻消息
用户2 订阅的内容: 我是一条天气消息
用户3 订阅的内容: 我是一条天气消息

总结

有了这个订阅发布模式了,就可以解决类似订单状态改变后的处理逻辑了

  1. 创建一个订单主题
  2. 创建一个观察者来订阅这个订单主题
  3. 当订单状态有变化时,通过订单主题发布这个订单
  4. 这时候只要订阅了这个订单主题的观察者就能收到消息,然后就可以处理这个状态有变化的订单了

java.util 包里也有 Observable Observer

不过它是通过被观察者主动添加观察者来实现的,当有消息了,调用 notifyObservers() 方法来通知观察者

这种做法还需要被观察者去维护观察者,不太好,还不如让观察者主动去订阅干脆

写博客不易,转载请保留原文链接,谢谢!

原文链接: https://tomoya92.github.io/2019/04/08/java-subscribe-publish/

Java里观察者模式(订阅发布模式)的更多相关文章

  1. AngularJS的简单订阅发布模式例子

    控制器之间的交互方式广播 broadcast, 发射 emit 事件 类似于 js中的事件 , 可以自己定义事件 向上传递直到 document 在AngularJs中 向上传递直到 rootScop ...

  2. saltstack系列(三)——zmq订阅/发布模式

    zmq订阅发布模式 server端代码: #coding=utf-8 ''''' 服务端,发布模式 ''' import zmq from random import randrange contex ...

  3. Publisher/Subscriber 订阅-发布模式

    Publisher/Subscriber 订阅-发布模式 本博后续将陆续整理这些年做的一些预研demo,及一些前沿技术的研究,与大家共研技术,共同进步. 关于发布订阅有很多种实现方式,下面主要介绍WC ...

  4. 设计模式---订阅发布模式(Subscribe/Publish)

    设计模式---订阅发布模式(Subscribe/Publish) 订阅发布模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象.这个主题对象在自身状态变化时,会通知所有订阅者对象,使 ...

  5. RabbitMQ下的生产消费者模式与订阅发布模式

    所谓模式,就是在某种场景下,一类问题及其解决方案的总结归纳.生产消费者模式与订阅发布模式是使用消息中间件时常用的两种模式,用于功能解耦和分布式系统间的消息通信,以下面两种场景为例: 数据接入   假设 ...

  6. Kafka下的生产消费者模式与订阅发布模式

    原文:https://blog.csdn.net/zwgdft/article/details/54633105   在RabbitMQ下的生产消费者模式与订阅发布模式一文中,笔者以“数据接入”和“事 ...

  7. js设计模式之代理模式以及订阅发布模式

    为啥将两种模式放在一起呢?因为这样文章比较长啊. 写博客的目的我觉得首要目的是整理自己的知识点,进而优化个人所得知识体系.知识成为个人的知识,就在于能够用自己的话表达同一种意义. 本文是设计模式系列文 ...

  8. 订阅发布模式eventEmiter

    // 订阅发布模式 class EventEmitter { constructor() { this._events = {}; } on(name, callback) { if (this._e ...

  9. ionic2踩坑之订阅发布模式的实现

    原文地址:http://www.cnblogs.com/eccainiao/p/6429536.html 转载请说明. 在ionic2中实现订阅发布模式,需要用到Events. Events下面有三个 ...

随机推荐

  1. 填平新版本Xcode安装插件不成功的坑

    一般情况下,安装xcode不成功现象基本上都出现在更新xcode或者重装之后出现的情况,下面原理性德东西,我就不赘述了,度娘上很容易看到,通过这段只是希望大家花费尽量少得时间将xcode插件安装成功. ...

  2. 吴裕雄--天生自然 PYTHON3开发学习:XML 解析

    <collection shelf="New Arrivals"> <movie title="Enemy Behind"> <t ...

  3. Papa开启“点播孙子”模式,新型老年人服务能在国内扎根吗?

    "互联网+"对多个行业的全面赋能和渗入,的确让我们的生活与工作处处充满了便利.很多"跑断腿"才能办的事,现在只要在PC.智能手机上滑动鼠标.点击屏幕就能轻松搞定 ...

  4. 曾经倍受年轻人追棒的Facebook为何如今却被称为“老年人社交网站”?

    一直以来,Facebook都被视为最受年轻人欢迎的社交媒体.毕竟此前在社交领域,能跟Facebook这一庞然巨物掰手腕的网站.应用几乎还没出现.但很显然,随着Instagram和Snapchat等新型 ...

  5. Iterator模式

    Iterator英文意思是重复做某件事,中文翻译为迭代器,这个设计模式中主要有Iterator(迭代器),ConcreteIterator(具体的迭代器),Aggergate(集合),Concrete ...

  6. C++ 类中使用dllimport和dllexport

    在Windows平台下: 您可以使用dllimport或dllexport属性声明C ++类.这些形式意味着导入或导出整个类.以这种方式导出的类称为可导出类. 以下示例定义可导出的类.导出其所有成员函 ...

  7. day32-socketserver

    #socketserver 是在socket基础上进行了封装,它让server可以实时跟多个client进行通信. #thread线程:一个程序有一个线程,一个线程是调度cpu的最小单位.程序运行才产 ...

  8. linux文件系统与链接

    Linux的文件属性图1 图1   linux的文件属性 ls -lhi -l 长格式 -h 人性化 -i inodo -d 看目录自己的信息 inode 源自于文件系统 分区 平面设计图 格式化 施 ...

  9. android版本更新框架、新闻客户端、音乐播放器、自定义View、Github客户端、指南针等源码

    Android精选源码 XUpdate 一个轻量级.高可用性的Android版本更新框架 Android一个可定制的圆形进度条 Android自定义View分享 打钩动画源码 android音乐文件播 ...

  10. 71)PHP,使用cookie的语法问题

    1) 为啥用数组的形式,就是这样好区分,你看都是跟student相关的东西, (2)