每个变化过后,都有观察者在如影随形——观察者模式
大家好,我是徒手敲代码。
今天来介绍一下观察者模式。
想象一个场景,小明关注了一个公众号,当公众号更新推文时,小明会收到通知。此时,小明可以选择是否查看这些更新的推文,而不用主动点开这个公众号的主页,才知道他有没有更新。
观察者模式总共有两个东西,一个是观察者,一个是被观察者。上述场景中,小明是观察者,而公众号是被观察者。而公众号有多个粉丝,相应的,被观察者需要维护一个观察者的列表,当被观察者的状态发生变化时,会自动通知这些观察者,使得观察者做出动作。
这种模式实现了对象间的松耦合,允许观察者和被观察者之间的交互,而不需要彼此直接了解彼此的细节。
下面用代码来模拟出这个场景。
一个公众号的类,一个小明的类,
假设不用观察者模式,公众号发布文章,小明是无感知的,需要每隔一段时间就去看看是否更新
class OfficialAccount {
private List<String> articles = new ArrayList<>();
public void publishNewArticle(String article) {
articles.add(article);
System.out.println("公众号发布了新文章:" + article);
}
}
class XiaoMing {
public void checkForNewArticles(OfficialAccount officialAccount) {
for (String article : officialAccount.getArticles()) {
System.out.println("小明发现新文章:" + article);
}
}
}
// 使用示例
OfficialAccount officialAccount = new OfficialAccount();
XiaoMing xiaoMing = new XiaoMing();
officialAccount.publishNewArticle("Java零基础入门");
// 小明发现新文章:Java零基础入门
xiaoMing.checkForNewArticles(officialAccount);
officialAccount.publishNewArticle("观察者模式详解");
// 小明发现新文章:观察者模式详解
xiaoMing.checkForNewArticles(officialAccount);
在这个场景下,小明必须定期手动检查公众号是否有新推文,这不仅麻烦,还可能导致错过实时更新。
如果公众号一天发几十篇,小明怕是要每时每刻都盯着手机看!这种设计显然不够智能和高效,不符合现实生活中,我们期待的即时推送体验。
所以,我们需要引入观察者模式,让小明能够躺着接收新文章通知。
首先,定义一个观察者接口:
public interface Observer {
void update(List<String> newArticles);
}
接着,改造公众号类,让它能维护一个观察者列表,并在发布新文章时通知所有观察者:
public class OfficialAccount {
private List<String> articles = new ArrayList<>();
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void publishNewArticle(String article) {
articles.add(article);
System.out.println("公众号发布了新文章:" + article);
List<String> newArticles = Collections.singletonList(article);
for (Observer observer : observers) {
observer.update(newArticles);
}
}
}
最后,让小明成为观察者,实现Observer
接口:
public class XiaoMing implements Observer {
@Override
public void update(List<String> newArticles) {
for (String article : newArticles) {
System.out.println("小明收到新文章通知:" + article);
}
}
}
// 使用示例
OfficialAccount officialAccount = new OfficialAccount();
XiaoMing xiaoMing = new XiaoMing();
officialAccount.addObserver(xiaoMing);
// 小明收到新文章通知:Java零基础入门
officialAccount.publishNewArticle("Java零基础入门");
// 小明收到新文章通知:观察者模式详解
officialAccount.publishNewArticle("观察者模式详解");
UML图如下:
这样一来,公众号每次更新,都会调用其观察者的update
方法,而不需要观察者主动去调。
如果想要继续增加新的观察者,只需要实现Observer
即可,原有的类不受影响,解耦观察者和被观察者。
实际应用
在 Spring 框架中,ApplicationListener
接口就运用了观察者模式。只要某个类实现了ApplicationListener
接口,就会在该事件发生时接收到通知。
比如:ContextRefreshedEvent
就是Spring提供的一种预定义事件,表示ApplicationContext(应用上下文)被初始化或刷新完成。
转载自:https://juejin.cn/post/7361241610070245413