1.观察者模式
概念:定义对象间的一种一对多的依赖关系。当一个对象的状态发生变化时,所有依赖它的对象都会得到通知并被自动更新。
模式中的角色:
抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
我们首先来看一下观察者模式的UML图:
话不多说,来看看我用java实现的观察模式的场景。该实现的功能描述是:黄明是一个气象台的工作人员,他需要向他的女朋友和妈妈提供最新的天气信息,以完成女朋友和其约会,妈妈逛街购物的功能。(呵呵,例子有点俗)。来看代码吧!
(1)抽象主题(WeatherSubject)
import java.util.ArrayList;
import java.util.List;
/*
* 目标对象,它知道观察它的观察者,并提供注册(添加)和删除的观察者的接口
*/
public class WeatherSubject {
//用来保存注册的观察者对象
private List<Observer> observers=new ArrayList<>();
//把订阅天气的人添加到订阅者列表
public void attach(Observer observer){
observers.add(observer);
}
//删除集合中指定订阅天气的人
public void detach(Observer observer){
observers.remove(observer);
}
//天气变化时,通知所有订阅天气的人
protected void notifyObservers(){
for(Observer observer:observers){
observer.update(this);
}
}
}
(2)具体主题(ConcreteWeatherSubject)
/*
* 具体的目标对象,负责把有关状态存入到相应的观察者对象中
*/
public class ConcreteWeatherSubject extends WeatherSubject {
//目标对象的状态
private String weatherContent;
public String getWeatherContent() {
return weatherContent;
}
public void setWeatherContent(String weatherContent) {
this.weatherContent = weatherContent;
this.notifyObservers();
}
}
(3)抽象观察者(Observer)
/*
* 这是一个观察者接口,定义一个更新的接口给那些在目标发生改变的时候被通知的对象
*/
public interface Observer {
/*
* 更新的接口
*/
public void update(WeatherSubject subject);
}
(4)具体观察者(ConCreteObserver)
/*
* 具体的观察者对象,实现更新的方法,使自身的状态和目标的状态一致
*/
public class ConcreteObserver implements Observer {
//观察者名字,谁收到了这个消息
private String observerName;
//天气内容的情况
private String weatherContent;
//提醒内容
private String remindThing;
public String getObserverName() {
return observerName;
}
public void setObserverName(String observerName) {
this.observerName = observerName;
}
public String getWeatherContent() {
return weatherContent;
}
public void setWeatherContent(String weatherContent) {
this.weatherContent = weatherContent;
}
public String getRemindThing() {
return remindThing;
}
public void setRemindThing(String remindThing) {
this.remindThing = remindThing;
}
@Override
public void update(WeatherSubject subject) {
weatherContent=((ConcreteWeatherSubject)subject).getWeatherContent();
System.out.println(observerName+"收到了"+weatherContent+","+remindThing);
}
}
public class Client {
public static void main(String[] args) {
//1.创建目标
ConcreteWeatherSubject weather=new ConcreteWeatherSubject();
//2.创建观察者
ConcreteObserver observerGirl=new ConcreteObserver();
observerGirl.setObserverName("黄明的女朋友");
observerGirl.setRemindThing("和黄明约会");
ConcreteObserver observerMum=new ConcreteObserver();
observerMum.setObserverName("黄明的妈妈");
observerMum.setRemindThing("购物的好天气");
//3.注册观察者
weather.attach(observerGirl);
weather.attach(observerMum);
//4.发布天气
weather.setWeatherContent("明天天气晴朗,气温28度");
}
}
(6)运行结果
2.观察者模式优缺点
优点:观察者模式实现了观察者和目标之间的抽象耦合;观察者模式实现了动态联动;观察者模式支持广播通信
缺点:可能引起无谓的操作(不管观察者愿不愿意,一旦有更新都会通知)。
3.观察者模式的应用场景
(1)当一个对象的改变需要改变其它对象时,而且它不知道具体有多少个对象有待改变时。
(2)当一个抽象某型有两个方面,其中一个方面依赖于另一个方面状态的变化,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。
(3)当一个对象必须通知其它的对象,但是你又不希望这个对象和其它被它通知的对象是松散耦合的。