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

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

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

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

然后,从一些资讯网站上的订阅功能想到了是否可以使用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. VS Code之Vue开发常用插件

    Auto Close Tag 自动补全html标签 Auto Rename Tag 同步更改html尾标签 ESLint ESlint语法提示 settings.json 文件 "eslin ...

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

    import pymongo myclient = pymongo.MongoClient("mongodb://localhost:27017/") mydb = myclien ...

  3. 897A. Scarborough Fair# 斯卡布罗集市(模拟)

    题目出处:http://codeforces.com/problemset/problem/897/A 题目大意:将某个范围内的某个字符换成另外一个字符 #include<iostream> ...

  4. 第一章:基于面向对象的UML

    1.1什么是面向对象 面向对象程序设计(Object-Oriented Programming,OOP)立足于创建软件代码的重复使用,具有更好地模拟现实世界的能力,这使它被公认为是自上而下编程的最佳选 ...

  5. 缩写: i = i + 1 和 i += 1,可以看做是 i 自加的值 是1。

    i +=  1; 这样有助于记忆: i自加的值等于1

  6. fibonacci-Heap(斐波那契堆)原理及C++代码实现

    斐波那契堆是一种高级的堆结构,建议与二项堆一起食用效果更佳. 斐波那契堆是一个摊还性质的数据结构,很多堆操作在斐波那契堆上的摊还时间都很低,达到了θ(1)的程度,取最小值和删除操作的时间复杂度是O(l ...

  7. PictureService

    package me.zhengjie.tools.service; import me.zhengjie.tools.domain.Picture; import org.springframewo ...

  8. 算法笔记4.3递归 问题 A: 吃糖果

    问题 A: 吃糖果 题目描述 名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名(盒内共有 N 块巧克力,20 > N >0). 妈妈告诉名名每天可以吃一块或者两块巧克力. 假设名 ...

  9. 微信中的APP、公众号、小程序的openid及unionid介绍

    微信中的APP.公众号.小程序的openid及unionid介绍 1.unionid 如果开发者拥有多个移动应用.网站应用.和公众帐号(包括小程序),可通过 UnionID 来区分用户的唯一性,因为只 ...

  10. zcat|subprocess.check_all|subprocess.Popen|gzip|readline()

    #!/usr/bin/python from subprocess import check_call import subprocess import gzip ''' $ zcat 160121_ ...