观察者模式
观察者模式(Observer Pattern),又叫发布-订阅(Publisher/Subscribe)模式,模型-视图模式,源-监听器模式或从属者模式。定义一种一对多的依赖关系,一个主题对象可以同时被多个监听者同时监听,使得每当主题对象状态发生变化时,所有依赖于它的对象都会得到通知并被自动更新。属于行为型模式。
应用场景
- 当一个抽象模型包含两个方面内容,其中一个方面依赖于另一个方面
- 一个或多个对象的变化依赖于另一个对象的变化
- 实现类似广播机制的功能,无需知道具体收听者,只需分发广播,系统中感兴趣的对象会自动接收该广播。
- 多层级嵌套使用,形成一种链式触发机制。使得事件具备跨域通知
角色
- 抽象主题(Subject):指被观察的对象。该角色是一个抽象类或接口,定义了增加,删除,通知观察者对象的方法
- 具体主题(ConcreteSubject):具体被观察者,当其内部状态发生变化时,会通知已注册的观察者
- 抽象观察者(Observer):定义了响应通知的更新 方法
- 具体观察者(ConcreteObserver):在得到状态更新时,会自动做出响应
使用
一般很少自己去实现,当然真的要去实现,可以在被观察者中维护一份观察者列表,支持注册注销等操作,有一个通知方法即可
JDK本身也提供了该模式的API,将类继承Observeble即可作为被观察者,实现接口Observer,并重写update方法即可作为观察者。使用时只需要将观察者通过addObserver注册进去即可
当然也可以使用谷歌提供的工具,需要引入依赖:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
然后通过注解标明监听者即可。
代码如下:
创建Vo 与 PoJo模拟两种类型的事件,只会监听对应的事件
package com.caozz.demo2.observer.guava;
public class Pojo {
private String name;
public Pojo(String name) {
this.name = name;
}
@Override
public String toString() {
return "Pojo{" +
"name='" + name + '\'' +
'}';
}
}
package com.caozz.demo2.observer.guava;
public class Vo {
private String name;
public Vo(String name) {
this.name = name;
}
@Override
public String toString() {
return "Vo{" +
"name='" + name + '\'' +
'}';
}
}
package com.caozz.demo2.observer.guava;
import com.google.common.eventbus.Subscribe;
public class PojoEvent {
@Subscribe
public void observer(Pojo pojo){
System.out.println("执行PojoEvent方法,传参为:" + pojo);
}
}
package com.caozz.demo2.observer.guava;
import com.google.common.eventbus.Subscribe;
public class VoEvent {
@Subscribe
public void observer(Vo arg){
// if(arg instanceof Vo){
System.out.println("执行VoEvent方法,传参为:" + arg);
// }
}
}
package com.caozz.demo2.observer.guava;
import com.google.common.eventbus.EventBus;
public class Test {
public static void main(String[] args) {
EventBus eventBus = new EventBus();
PojoEvent guavaEvent = new PojoEvent();
VoEvent voEvent = new VoEvent();
eventBus.register(guavaEvent);
eventBus.register(voEvent);
eventBus.post(new Pojo("Tom"));
eventBus.post(new Vo("Jerry"));
}
}