观察者设计模式也被称为监听者模式或发布订阅模式。在 GoF 的《设计模式》一书中,它的定义是这样的:“在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知”。
可以看出,这样的代码非常的优雅,主逻辑(商品类主题变价)和其他逻辑(比如价格观察者的逻辑处理、产品id处理等等)进行了解耦,实现一对多,只要变价,就会广播消息,观察者就可以执行自己的逻辑。
具体代码实现如下:
@Data
public class Goods {
private long id;
private String price;
}
定义和实现主题类
public interface Subject{ void registerObserver(Observer observer); void notifyObserver(Goods goods); } @Slf4j public class GoodsSubject implements Subject { private List list = Lists.newArrayList(); @Override public void registerObserver(Observer observer) { list.add(observer); } @Override public void notifyObserver(Goods goods) { list.forEach(e -> e.executeMethod(goods)); } public void changePrice(Goods goods) { log.info("商品价格变动"); this.notifyObserver(goods); //通知到观察者 } }
然后定义和实现观察者
public interface Observer {
void executeMethod(Goods goods);
}
@Slf4j
public class PriceObserver implements Observer{
@Override
public void executeMethod(Goods goods) {
log.info("对商品价格进行处理…… price = " + goods.getPrice());
}
}
进行测试
@Test
public void testObserver() {
//变动的商品
Goods goods = new Goods();
goods.setId(10L);
goods.setPrice("200");
//商品主题
GoodsSubject goodsSubject = new GoodsSubject();
//注册观察者
PriceObserver priceObserver = new PriceObserver();
goodsSubject.registerObserver(priceObserver);
//执行变价
goodsSubject.changePrice(goods);
}
打印结果:
[main] INFO c.j.o.GoodsSubject - 商品价格变动
[main] INFO c.j.o.PriceObserver - 对商品价格进行处理…… price = 200
这个案例提供的是同步阻塞式观察者模式,也可以单独开线程处理观察者逻辑,即异步非阻塞。
在SpringBoot中,可以使用ApplicationContext实现事件的发布,使用@EventListener实现事件监听,可以额外使用@Async("threadPoolUtil")实现异步监听。参考《SpringBoot应用——项目搭建指北》的Spring的异步监听机制章节。
Spring的监听,万变不离其宗,不过采用的形式不一样,Spring是通过消息发送方法参数类型和消息监听方法参数类型进行反射匹配,组合到一起的。容器启动的时候会将带有@EventListener注解的类注册到观察者列表中,当使用ApplicationContext发送消息的时候,会根据消息的类型Object反射判断,应该由哪个观察者进行处理。



