设计模式其实不难,难得是根据实际情况使用合适的设计模式来实现业务逻辑。
观察者模式简介
观察者模式(Observer Pattern)是处理一对多关系的时候可以使用观察者模式。比如:一个A对象被修改,有一些依赖他的对象会观察到A被修改了,这些依赖A的对象就被称为观察者,而对象A就是被观察者。
主要使用的类
- Observer:观察者接口(或者是抽象类),用来规范观察者需要实现哪些方法。
- ObServer的实现类:用来具体实现观察者。
- Subject:主体接口(或者是抽象类),用于规范主体需要实现那些方法。这里面的主体也就是被观察者。
- Subject的实现类:用于根据需求实现主体类。
举个例子
假如有个开发天气预报软件的公司,他们现在需要实现一个功能。他们有一个天气的数据中心,里面会实时根据当前天气情况更新数据。现在需要实现每次数据更新的时候,他们的web网站应用、安卓手机上的app、IOS手机上的app都会更新数据。
分析
在这个例子中:我们的web应用、安卓手机上的app、IOS手机上的app都是一个个观察者。而天气的数据中心就是一个被观察者。
实现
- 首先实现我们的观察者接口:Observer
public interface Observer {
//weatherMsg是天气信息
void update(String weatherMsg);
}
在此例子中,无论是web还是app更新,都是需要提供一个天气的数据的。所以更新方法需要一个形参代表天气信息的数据。
- 实现web的监听者:WebObserver
public class WebObserver implements Observer {
@Override
public void update(String weatherMsg) {
System.out.println("更新Web应用的天气数据=>"+weatherMsg);
}
}
- 实现安卓app的监听者:AndroidObserver
public class AndroidObserver implements Observer {
@Override
public void update(String weatherMsg) {
System.out.println("更新安卓APP上的天气数据=>"+weatherMsg);
}
}
- 实现IOSapp的监听者:IosObserver
public class IosObserver implements Observer{
@Override
public void update(String weatherMsg) {
System.out.println("更新苹果APP上的天气数据=>"+weatherMsg);
}
}
- 监听者都实现了,下下面实现被监听者(也就是主体)接口:Subject
public interface Subject {
//添加一个观察者,告诉被观察者有个对象在观察你。
boolean register(Observer observer);
//移除一个观察者,告诉被观察者此对象不再观察你了。
boolean remove(Observer observer);
//通知所有观察者,状态改变了。
void notifyAllObserver();
}
- 实现被观察者,也就是例子中的天气数据中心。
public class WeatherDataCenterSubject implements Subject {
//一个list对象,用于储存哪些对象观察了此对象。
private List observers=new ArrayList<>();
//因为是小的案例,所以这里没有处理线程,真正开发中肯定不能这样写的。要根据实际情况来。
private String weatherMsg="";
public WeatherDataCenterSubject(String currentWeather){
this.weatherMsg=currentWeather;
System.out.println("当前天气 => "+currentWeather);
}
//数据中心的天气数据更新
public void updateData(String weather){
System.out.println("天气更新 => "+weather);
//调用通知方法,通知所有观察者数据中心的数据更新了
this.notifyAllObserver();
}
@Override
public boolean register(Observer observer) {
return observers.add(observer);
}
@Override
public boolean remove(Observer observer) {
return observers.remove(observer);
}
@Override
public void notifyAllObserver() {
for(Observer item : observers){
item.update(weatherMsg);
}
}
}
- 测试
public class Test {
public static void main(String[] args) {
WeatherDataCenterSubject weatherDataCenter=new WeatherDataCenterSubject("晴,17摄氏度,空气质量优");
weatherDataCenter.register(new WebObserver());
weatherDataCenter.register(new AndroidObserver());
weatherDataCenter.register(new IosObserver());
System.out.println("======================");
weatherDataCenter.updateData("阴天,16摄氏度,空气质量中");
System.out.println("======================");
weatherDataCenter.updateData("小雨,13摄氏度,空气质量优");
}
}
输出结果:
当前天气 => 晴,17摄氏度,空气质量优
======================
天气更新 => 阴天,16摄氏度,空气质量中
更新Web应用的天气数据=>晴,17摄氏度,空气质量优
更新安卓APP上的天气数据=>晴,17摄氏度,空气质量优
更新苹果APP上的天气数据=>晴,17摄氏度,空气质量优
======================
天气更新 => 小雨,13摄氏度,空气质量优
更新Web应用的天气数据=>晴,17摄氏度,空气质量优
更新安卓APP上的天气数据=>晴,17摄氏度,空气质量优
更新苹果APP上的天气数据=>晴,17摄氏度,空气质量优
如何拓展?
如果这时候又开发个TV版的天气预报软件,就只需要实现一个TVObserver,然后注册到数据中心就好。如:weatherDataCenter.register(new TVObserver());
观察者模式有什么缺点
上面的例子中,观察者是通过注册方法添加到被观察者的一个list中的。然后每次被观察者数据改变了都会遍历list,执行相应的方法。这样如果监听者特别多,那么就损失效率。
最后
从代码上看观察者模式叫通知模式更合适吧?