一、观察者模式的概念
观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
二、什么时候使用观察者模式
当一个对象被修改,或者发生某些变化时,需要自动通知依赖它的一些对象,则可以使用观察者模式。
例如:当汽车熄火时,需要更新汽车的定位、发送熄火的通知、生成本次的行程,就可以使用观察者模式,这个例子中发生变化的位置是熄火,那么发生熄火需要通知依赖它的一些对象,就是定位、通知和行程。
下面来看看,如何用Java语言实现观察者模式。
三、怎么使用观察者模式
3.1 不适用观察者模式的弊端
用上面说的业务场景为例,如果不使用观察者模式来实现,可以看下面的伪代码:
public class EngineOffEvent() {
public void engineOff() {
Location localtion = new Localtion();
Notification notification = new Notification();
Trip trip = new Trip();
localtion.update();
notification.notify();
trip.createTrip();
}
}
这种做法有如下两个主要弊端:
- 耦合度高:可以看到EngineOffEvent类耦合了所有其他的业务类,造成维护困难;
- 扩展性差:当需要在熄火时做新业务时,需要修改engineOff方法内的代码,违反了开闭原则;
- 灵活度低:不能控制通知的对象个数;
3.2 如何用观察者模式解决问题
根据上面的需求,用观察者模式进行设计,下面看看类图和代码:
代码如下:
/**
* 观察者接口。
* */
public interface Observer {
/**
* 当气象监测数据改变时,主题会把这些状态值当作方法的参数,传送给观察者。
* */
void update(String data);
}
public class LocaltionObserver implements Observer{
public void update(String data) {
System.out.println(data + ":更新位置。");
}
}
public class NotificationObserver implements Observer{
public void update(String data) {
System.out.println(data + ":发送通知。");
}
}
public class TripObserver implements Observer {
public void update(String data) {
System.out.println(data + ":生成行程。");
}
}
/**
* 主题接口。
* */
public interface Subject {
/**
* registerObserver和removeObserver方法都需要一个观察者作为变量,该观察者是用来注册或被删除的。
* */
void registerObserver(Observer ob);
void removeObserver(Observer ob);
/**
* 当主题的状态改变时,这个方法会被调用,已通知所有的观察者。
* */
void notifyObservers(String data);
}
// 熄火事件
public class EngineOffEvent implements Subject {
// 观察者对象集合
private List<Observer> observers;
public EngineOffEvent() {
observers = new ArrayList<Observer>();
}
// 注册观察者
public void registerObserver(Observer ob) {
observers.add(ob);
}
// 移除观察者
public void removeObserver(Observer ob) {
int index = observers.indexOf(ob);
if (index >= 0)
observers.remove(index);
}
// 发生变化进行通知
public void notifyObservers(String data) {
// 通知全部观察者
for (Observer ob : observers) {
ob.update(data);
}
}
}
// 使用
public class Client {
public static void main(String[] args) {
Subject subject = new EngineOffEvent();
subject.registerObserver(new LocaltionObserver());
subject.registerObserver(new NotificationObserver());
subject.registerObserver(new TripObserver());
subject.notifyObservers("京A88888熄火");
}
}
//京A88888熄火:更新位置。
//京A88888熄火:发送通知。
//京A88888熄火:生成行程。
观察者模式主要分为两部分:
- Subject,主题,是发生变化的那个对象,例子中是熄火事件;
- Observer,观察者,是发生变化后需要通知的多个对象,例子中是通知、位置和行程;
在使用时,可以动态添加或者删除观察者,灵活配置。
3.3 观察者模式的好处
- 耦合度低:解除了3.1小节中,EngineOffEvent类与其他的业务类的耦合;
- 扩展性高:当需要在熄火时做新业务时,创建一个新对象实现Observer,然后注册到Subject即可;
- 灵活度高:可以随意添加或移除Observer;
3.4 其他可以注意的地方
Java内置了观察者模式:
-
java.util.Observable(类)
-
java.util.Observer(接口)
可以使用内置的观察者,但是其中Observable对应的是上面例子中的Subject,他是一个Class而不是Interface,如果使用内置的接口,则需要把宝贵继承机会用掉,若你的类已经使用了继承关系,则无法使用。
四、总结
上面的观察者模式,从代码上来说,就是面相接口编程,在Subject中有一个List<Observer>,在发生变化后,循环调用List中的对象的方法,确保都通知到,并且可以对List进行添加和删除。
从业务上来说,当发生某个事件后,需要批量通知许多个对象。则可以使用这个模式。
以上就是我对观察者模式的一些理解,有不足之处请大家指出,谢谢。
来源:oschina
链接:https://my.oschina.net/u/2450666/blog/4291930