观察者设计模式

观察者设计模式也被称为监听者模式发布订阅模式。在 GoF 的《设计模式》一书中,它的定义是这样的:“在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知”。

观察者需要注册到被观察者中,被观察者状态更新需要调用观察者update() 方法。但是,在跨进程的实现方式中,我们可以利用消息队列实现彻底解耦,观察者和被观察者都只需要跟消息队列交互,观察者完全不知道被观者的存在,被观察者也完全不知道观察者的存在。
在这里插入图片描述
可以看出,这样的代码非常的优雅,主逻辑(商品类主题变价)和其他逻辑(比如价格观察者的逻辑处理、产品id处理等等)进行了解耦,实现一对多,只要变价,就会广播消息,观察者就可以执行自己的逻辑。
具体代码实现如下:

/**
 * 商品
 */
@Data
public class Goods {

    /**
     * 商品id
     */
    private long id;

    /**
     * 价格
     */
    private String price;
}

定义和实现主题类

/**
 * 订阅的主题
 */
public interface Subject<T> {

    /**
     * 注册观察者
     */
    void registerObserver(Observer observer);

    /**
     * 通知观察者
     */
    void notifyObserver(Goods goods);
}

/**
 * 商品主题
 */
@Slf4j
public class GoodsSubject implements Subject<Goods>{

    /**
     * 观察者list
     */
    private List<Observer> 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反射判断,应该由哪个观察者进行处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值