大家好,你还在面向 for 循环编程吗?
还有谁不会用观察者模式吗?
本篇栈长带来《观察者模式》实践及实战~
什么是观察者模式?
观察者模式(Observer Pattern)定义了对象间的一种一对多的依赖关系,这样只有一个对象的状态产生扭转,其依赖的所有相干对象都会失去告诉并自动更新。
在观察者模式中,产生扭转的对象叫做 察看指标 ,而被告诉更新的对象称为 观察者,一个察看指标对应多个观察者,观察者个别是一个列表汇合,能够依据须要动静减少和删除,易于扩大。
应用观察者模式的长处在于察看指标和观察者之间是形象松耦合关系,升高了两者之间的耦合关系。
公布 - 订阅模式
观察者模式很多中央也叫 公布-订阅 模式(Publish/Subscribe),其实也能够这么了解,不过两者之间还是略有不同。
观察者模式中的观察者是间接绑定察看指标,察看指标要保护一套观察者列表,两者是有一个基于接口的组合依赖关系的,所以说观察者模式尽管是松耦合的,但并不是齐全解耦的。
而 公布-订阅 模式中的发布者和订阅者两者并没有任何分割,发布者通过中间方公布一个主题(Topic),订阅者通过中间方(调度核心)订阅一个主题(Topic),发布者状态的变更也并不会间接告诉订阅者,而要通过中间方进行告诉,或者订阅者自行从中间方拉取,所以说 公布-订阅 模式是齐全解耦的。
一图搞懂它们的关系:
从图片看两者是有差异的,对立都叫观察者模式,也没故障。
观察者模式轮子
因观察者模式利用比拟宽泛,所以 JDK 工具包从 1.0 版本外面自带了观察者模式模板套装,咱们依据其模板很不便就能实现观察者模式,不须要再反复造轮子了。
观察者指标类:
java.util.Observable
外面两个最重要的变量:
- changed:察看指标状态是否变更,默认为:false;
- obs:观察者列表(observers),一个线程平安的列表汇合:Vector,默认为空集合;
外面的重要的办法都是和察看指标状态和观察者相干的,一看就分明,这里就不介绍了。
观察者接口:
java.util.Observable
public interface Observer {
/**
* This method is called whenever the observed object is changed. An
* application calls an <tt>Observable</tt> object's
* <code>notifyObservers</code> method to have all the object's
* observers notified of the change.
*
* @param o the observable object.
* @param arg an argument passed to the <code>notifyObservers</code>
* method.
*/
void update(Observable o, Object arg);
}
观察者接口只有一个 update 办法,用来告诉观察者本人更新。
观察者模式实战
OK,晓得了 JDK 自带了这两个东东,当初就来实现一个简略的观察者模式的利用场景,模仿公众号文章推送,察看指标是栈长我,观察者是你们大家,我在公众号 Java 技术栈推一篇文章,你们都能接管到更新告诉并能浏览。
新增察看指标类:
import lombok.Getter;
import java.util.Observable;
/**
* 察看指标:栈长
* 起源微信公众号:Java 技术栈
*/
@Getter
public class JavaStackObservable extends Observable {
private String article;
/**
* 发表文章
* @param article
*/
public void publish(String article){
// 发表文章
this.article = article;
// 扭转状态
this.setChanged();
// 告诉所有观察者
this.notifyObservers();}
}
察看指标的逻辑是先发表文章,再扭转察看指标的状态,再告诉所有观察者。
咱们来重点看 notifyObservers 办法的源码:
先获取同步锁,判断状态是否更新,如已更新则清空察看指标状态,而后再应用 for 循环遍历所有观察者,一一调用观察者的更新办法告诉观察者更新。
新增观察者类:
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import java.util.Observable;
import java.util.Observer;
/**
* 观察者:读者粉丝
* 起源微信公众号:Java 技术栈
*/
@RequiredArgsConstructor
public class ReaderObserver implements Observer {
@NonNull
private String name;
private String article;
@Override
public void update(Observable o, Object arg) {
// 更新文章
updateArticle(o);
}
private void updateArticle(Observable o) {JavaStackObservable javaStackObservable = (JavaStackObservable) o;
this.article = javaStackObservable.getArticle();
System.out.printf("我是读者:%s,文章已更新为:%s\n", this.name, this.article);
}
}
观察者的逻辑是获取到观察者指标实例对象,而后再用察看指标对象的文章信息更新为本人的文章信息,最初输入某某某的文章已更新。
观察者只有实现 Observer 这个接口的 update 办法即可,用于察看指标进行调用告诉。
本节教程所有实战源码已上传到这个仓库:https://github.com/javastacks…
察看指标和观察者类结构图如下:
新增测试类:
/**
* 观察者:读者粉丝
* 起源微信公众号:Java 技术栈
*/
public class ObserverTest {public static void main(String[] args) {
// 创立一个察看指标
JavaStackObservable javaStackObservable = new JavaStackObservable();
// 增加观察者
javaStackObservable.addObserver(new ReaderObserver("小明"));
javaStackObservable.addObserver(new ReaderObserver("小张"));
javaStackObservable.addObserver(new ReaderObserver("小爱"));
// 发表文章
javaStackObservable.publish("什么是观察者模式?");
}
}
察看指标、观察者的创立并没有先后顺序要求,重点是发表文章告诉观察者之前,察看指标要增加观察者列表这一步不能少。
输入后果:
通过这个简略的文章推送实际,大家应该对观察者模式有一个根本的认知了,在理论工作当中也能够有很多场景拿去用,就一对多的依赖关系都能够思考应用观察者模式。
总结
不容易啊,陆陆续续又肝了大半天,你学会观察者模式了吗?
观察者模式的长处是为了给察看指标和观察者解耦,而毛病也很显著,从下面的例子也能够看出,如果观察者对象太多的话,有可能会造成内存泄露。
另外,从性能下面思考,所有观察者的更新都是在一个循环中排队进行的,所以观察者的更新操作能够思考做成线程异步(或者能够应用线程池)的形式,以晋升整体效率。
本节教程所有实战源码已上传到这个仓库:
https://github.com/javastacks…
好了,明天的分享就到这里了,前面栈长我会更新其余设计模式的实战文章,公众号 Java 技术栈第一工夫推送。Java 技术栈《设计模式》系列文章陆续更新中,请大家继续关注哦!
最初,感觉我的文章对你用播种的话,动动小手,给个在看、转发,原创不易,栈长须要你的激励。
版权申明:本文系公众号 “Java 技术栈 ” 原创,原创实属不易,转载、援用本文内容请注明出处,禁止剽窃、洗稿,请自重,尊重别人劳动成果和知识产权。
近期热文举荐:
1.600+ 道 Java 面试题及答案整顿(2021 最新版)
2. 终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!
3. 阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!
4.Spring Cloud 2020.0.0 正式公布,全新颠覆性版本!
5.《Java 开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞 + 转发哦!