观察者模式(Observer)是 JDK 中使用最多的模式之一
有时候,我们的对象需要在收到某些通知时及时作出响应,此时可以用观察者模式。观察者模式定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
可以以订阅报纸类比,出版社作为发布者,所有订阅了报纸的用户,在有新报纸出版时,都会收到一份最新的报纸。只不过,在观察者模式中,出版社叫做 主题(Subject),订阅者叫 观察者(Observer)。
主题(Subject)
主题就是发送通知的人。
1 2 3 4 5
| public interface Subject { void registerObserver(Observer observer); void removeObserver(Observer observer); void notifyObservers(); }
|
一个可以发布小说和新闻的报社,它维护了一个观察者列表,需要订阅这家报社的人,都会被加到这个 List 进来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class Publisher implements Subject { private List<Observer> observers; private String story; private String news;
Publisher(){ observers = new ArrayList<>(6); }
@Override public void registerObserver(Observer o) { observers.add(o); }
@Override public void removeObserver(Observer o) { observers.remove(o); }
@Override public void notifyObservers() { observers.forEach(o -> o.update(story, news)); }
public void setMessages(String story, String news){ this.story = story; this.news = news; notifyObservers(); } }
|
观察者(Observer)
观察者就是接收通知的人,当有通知来到,它自动会更新。
1 2 3
| public interface Observer { void update(String news); }
|
假设有个新闻爱好者,想订阅新闻:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class NewsObserver implements Observer { private String news;
@Override public void update(String story, String news) { this.news = news; displayNews(); }
public void displayNews(){ System.out.println(this.getClass().getName() + "获取到:" + this.news); } }
|
同理,小说爱好者,想订阅小说:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class StoryObserver implements Observer { private String story;
@Override public void update(String story, String news) { this.story = story; displayStory(); }
public void displayStory(){ System.out.println(this.getClass().getName() + "获取到:" + this.story); } }
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public static void main(String[] args) {
Publisher dailyPublisher = new Publisher();
Observer storyObserver = new storyObserver(); Observer newsObserver = new NewsObserver();
dailyPublisher.registerObserver(storyObserver); dailyPublisher.registerObserver(newsObserver);
dailyPublisher.setMessages("最新小说", "每日新闻"); }
|
结果:
1 2
| StoryObserver获取到:最新小说 NewsObserver获取到:每日新闻
|
Java 内置的观察者模式
在 java.util 包内,自带了 Observer接口
与 Observable类
,跟我们自己实现的观察者模式大同小异。但是,jdk内置的主题是继承Observable类
,而不是实现接口。但是在 java 9 中, 已经被标记为 deprecated
,原因是,他们的扩展性不够好,可以用 Listeners
代替。见 Observer is deprecated in Java 9. What should we use instead of it?