“这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战”
观察者模式是指对象之间一对多的依赖关系,每当那个特定对象改变状态时,所有依赖于它的对象都会得到通知并被自动更新。
通俗地来说,观察者模式实际上与报纸的订阅模式相同。报纸主要有两个角色:出版者和订阅者,出版者负责出版报纸,订阅者向出版者订阅报纸。当订阅者订阅报纸以后,出版者每次出版报纸,都会通知并推送给订阅者。
在观察者模式中,出版者称为被观察者,订阅者称为观察者。
模式结构
如图所示,观察者模式主要由两种角色组成:被观察者(Subject)和观察者(Observer)组成。
- 被观察者(Subject) :以接口的形式存在,需要被实际的被观察者(Concrete Subject)实现,维护了一个观察者列表,并有
attach()
,detach()
,notify()
三种方法。其中attach()
和detach()
分别负责添加和删除观察者。notify()
负责调用观察者的update()
方法进行通知和状态的更新。 - 观察者(Observer) :以接口的形式存在,需要被实际的观察者(Concrete Observer)实现,有
update()
一种方法,负责提供给被观察者调用来进行通知和状态的更新。
推模型和拉模型
观察者模式根据数据推送的方式,可以分为推模型
和拉模型
。
- 推模型:被观察者的数据更新后,向观察者通知并主动推送数据,不管被观察者需不需要。
- 拉模型:被观察者的数据更新后,向观察者通知,但并不主动推送数据。当观察者需要数据时,则可以主动从被观察者中拉数据。
推模型和拉模型,更多的是语义和逻辑上的区别,在代码实现的过程中,完全可以写成同时支持两种模型的通用参数形式,具体可见Java.util包下的Observer接口和Observable类。
具体实现
以报纸的订阅场景为例,有一个被观察者:报社,两个观察者:个人、企业。具体实现如下:
类图:
被观察者:
/**
* 被观察者的接口
*/
public interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyObserver();
}
/**
* 被观察者实现类:报社
*/
public class Newspaper implements Subject {
private List<Observer> observerList;
private String newspaperContent;
public Newspaper(){
observerList = new ArrayList<Observer>();
}
@Override
public void attach(Observer observer) {
observerList.add(observer);
}
@Override
public void detach(Observer observer) {
observerList.remove(observer);
}
@Override
public void notifyObserver() {
for (int i = 0; i < observerList.size(); i++) {
observerList.get(i).update(newspaperContent);
}
}
public String getNewspaperContent() {
return newspaperContent;
}
public void setNewspaperContent(String newspaperContent) {
this.newspaperContent = newspaperContent;
}
}
观察者:
/**
* 观察者接口
*/
public interface Observer {
void update(String newspaperContent);
}
/**
* 观察者实现类:人
*/
public class People implements Observer{
private String name;
private String newspaperContent;
public People(String name) {
this.name = name;
}
@Override
public void update(String newspaperContent) {
this.newspaperContent = newspaperContent;
System.out.println("我是"+this.name+",我收到了报纸,报纸内容是:"+this.newspaperContent);
}
}
/**
* 观察者实现类:企业
*/
public class Company implements Observer{
private String name;
private String newspaperContent;
public Company(String name) {
this.name = name;
}
@Override
public void update(String newspaperContent) {
this.newspaperContent = newspaperContent;
System.out.println(this.name+"收到了报纸,报纸内容是:"+this.newspaperContent);
}
}