设计模式:观察者模式(有利于代码解耦)
来源:互联网 发布:人工蜂群算法matlab 编辑:程序博客网 时间:2024/05/22 06:51
概念
首先,什么是观察者模式:多个观察者去监听主题,当主题发生变化的时候,主题会通知所有的观察者。
盗用网上的一个图:
从上图的结构可以看出,主题维护了一个观察者类型的链表,每当主题变化的时候,就会循环调用各个观察者的对应方法(这就是通知)。
在观察者模式中,又分为 推模型 和 拉模型。
- 推模型:主题向观察者推送详细信息。
- 拉模型:主题把自身作为一个参数发送给观察者,观察者需要什么信息,那么就 主题.getXX() 。
Java中的观察者模式
再来看看 Java中的观察者模式,最后再提一下 个人在 SpringBoot 中对于观察者模式的实际使用。
Java 提供了 Observer接口(观察者接口) 和 Observable 接口(被观察者接口 / 主题接口)。源码如下:
Observable 接口(被观察者接口 / 主题接口):
public class Observable { private boolean changed = false; private Vector<Observer> obs; public Observable() { obs = new Vector<>(); } public synchronized void addObserver(Observer o) { if (o == null) throw new NullPointerException(); if (!obs.contains(o)) { obs.addElement(o); } } public synchronized void deleteObserver(Observer o) { obs.removeElement(o); } public void notifyObservers() { notifyObservers(null); } public void notifyObservers(Object arg) { Object[] arrLocal; synchronized (this) { if (!changed) return; arrLocal = obs.toArray(); · clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); } public synchronized void deleteObservers() { obs.removeAllElements(); } protected synchronized void setChanged() { changed = true; } protected synchronized void clearChanged() { changed = false; } public synchronized boolean hasChanged() { return changed; } public synchronized int countObservers() { return obs.size(); } }
如上代码:通过 Vector 维护一个 观察者类型的数组。通过调用 notifyObeservers(Object arg) 方法 来通过观察者。在实现中,也是通过for 循环 通知。
Ps:注意:从代码上看,需要先设changed。
Observer接口(观察者接口):
public interface Observer { void update(Observable o, Object arg); }
这两个参数的含义为:
* @param o the observable object. * @param arg an argument passed to the <code>notifyObservers</code>
所以,此时即实现了 推模型,也实现了 拉模型。如果我们使用,那么分别实现这两个接口即可。
SpringBoot事件机制对于观察者模式的运用
那么在个人的实际运用中,做的是一个记账的服务,让别人来调用。当然,可以让别人直接在他们的业务处理后面,例如购买了XX东西,马上就直接调用我的记账服务,但是这样其实是一个紧耦合,由于是两个不同的业务,所以紧耦合感觉不太好。那么 观察者模式就有利于解耦。
对于Spring Boot 的事件机制,同样离不开 这2个东西-主题,观察者。 但是 ,spring boot 把 之前所说的通知,包装成了一个 Event。下面分析这三者。
SpringBoot的主题
Spring boot 的主题 可以 由 ApplicationContext 来充当。ApplicaitonContext 继承于 ApplicationEventPublisher。ApplicaiotnEventPublisher 源码如下:
public interface ApplicationEventPublisher { /** * Notify all listeners registered with this application of an application * event. Events may be framework events (such as RequestHandledEvent) * or application-specific events. * @param event the event to publish * @see org.springframework.web.context.support.RequestHandledEvent */ void publishEvent(ApplicationEvent event); }
其实该接口就是我们 发布事件的接口。
SpringBoot 的观察者
Spring Boot 的观察者由 ApplicationListener 来进行充当。源码如下:
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /** * Handle an application event. * @param event the event to respond to */ void onApplicationEvent(E event); }
可以看到, onApplicaiton(E event) 方法即 上文所说的 update 方法。
SpringBoot的Event
上文所说的 主题 和 观察者 都有体现,传输的消息 Spring Boot 使用了一个 ApplicationEvent 进行了封装,源码如下:
public abstract class ApplicationEvent extends EventObject { /** use serialVersionUID from Spring 1.2 for interoperability */ private static final long serialVersionUID = 7099057708183571937L; /** System time when the event happened */ private final long timestamp; public ApplicationEvent(Object source) { super(source); this.timestamp = System.currentTimeMillis(); } public final long getTimestamp() { return this.timestamp; } }
EventObject 源码:
public class EventObject implements java.io.Serializable { private static final long serialVersionUID = 5516075349620653480L; /** * The object on which the Event initially occurred. */ protected transient Object source; public EventObject(Object source) { if (source == null) throw new IllegalArgumentException("null source"); this.source = source; } public Object getSource() { return source; } public String toString() { return getClass().getName() + "[source=" + source + "]"; } }
由上面的代码 可知,其实 ApplicationEvent 就是 把需要传输的消息 封装起来。这个消息并没有想 Java 的实现那样推拉模型都实现了,而是 只实现了 拉模型 。
最后,我们程序中只需要 注入ApplicaitonContext 发送消息,实现 ApplicationListener 接口进行相应的处理即可。
总结
观察者模式实质是 有两个 东西:
- 一个是 主题
- 一个是观察者
主题中维护了 观察者列表的引用。当主题有变更的时候,循环调用观察者,通知其做相应的处理。另外,不论是 Java,还是 Spring ,都是利用这个原理,只是有不同的类充当 主题 和 观察者。
另外,观察者模式有一个好处:解耦。
- 设计模式:观察者模式(有利于代码解耦)
- Observer(观察者)设计模式代码实现
- 设计模式之观察者模式(解决、解耦的钥匙——观察者模式)
- 设计模式(观察者模式)
- 设计模式之观察者模式C++代码
- 设计模式,行为模式(观察者模式)
- 设计模式--观察者(监听)设计模式
- 设计模式(一)观察者设计模式
- 设计模式--观察者(监听)设计模式
- 模式设计:观察者模式
- 设计模式-----观察者模式
- 设计模式-观察者模式
- 设计模式--观察者模式
- 设计模式:观察者模式
- 设计模式-----观察者模式
- 设计模式:观察者模式
- 设计模式-观察者模式
- 设计模式 观察者模式
- Dubbo应用学习(2)
- Yii安装
- WIFI相关记录
- window.location.hash属性介绍
- SharePoint 2016 开发 工具Preview发布
- 设计模式:观察者模式(有利于代码解耦)
- OpenGL总结
- Ext.form.FieldSet字段集
- 通过UIView 获得它的控制器方法
- 矩形框融合
- HttpHost远程访问获取参数方式
- 一些Android学习资源
- Linux设置root不能直接ssh登录的方法
- windows server 2003系统下安装AndroidStudio失败