《一天一模式》— 观察者模式
时间: 2020-05-26来源:OSCHINA
一、观察者模式的概念 观察者模式(又被称为发布-订阅(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进行添加和删除。
从业务上来说,当发生某个事件后,需要批量通知许多个对象。则可以使用这个模式。
以上就是我对观察者模式的一些理解,有不足之处请大家指出,谢谢。
热门排行