设计模式——观察者模式

459 阅读4分钟

《Head First 设计模式》《设计模式之禅(第二版)》 学习笔记,码云同步更新中

如有错误或不足之处,请一定指出,谢谢~

目录

设计原则
设计模式

观察者模式

定义

定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会收到通知并自动更新

结构:
  • Subject:主题接口
  • ConcreteSubject:具体主题
  • Observer:观察者接口
  • ConcreteObserver:具体观察者
优点
  • 具体主题和具体观察者之间为松耦合关系
  • 符合“开闭原则”
缺点
  • 没有相应的机制使观察者知道主题是如何发生变化的
  • 如果观察者之间存在循环调用,会导致系统崩溃,需要特别注意
适用范围
  • 一个对象的改变需要触发其他多个对象的改变,但不知道具体有多少需要改变的对象,降低对象间的耦合
  • 一个对象需要通知很多其他对象,但不需要知道他们是谁
与发布-订阅模式的区别
  • 发布-订阅模式中,发布者不直接和订阅者通信,他们甚至不知道对方的存在。他们通过第三方信息中介进行通信
  • 观察者模式大多是同步的,而发布-订阅模式大多是异步的(消息队列)
其他
  • 在另一个例子中:气象台(主题)发布实时数据(间隔很短,假设1秒一次), 布告板(观察者)显示气温(有可能实时,也有可能每天一次,或者统计月平均数据)。 这种情况下观察者需要将接收到的数据缓存下来,然后在各自设定的时间对外展示。
  • 在JDK的java.util包中,提供了Observable类以及Observer接口,它们构成了Java语言对观察者模式的支持。
案例
  • 线上商城客户下单付款后,需要执行一系列业务逻辑,随时有可能增加或删去
    1. 发送短信
    2. 累计积分
    3. 购物节活动赠送小礼品
  • 原有实现:在付款成功后的方法中增加相关代码,等到不需要时再删除代码。
  • 问题:反复增删改付款核心逻辑,易出错,难维护。
  • 观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会收到通知并自动更新
    • 创建观察者(通知)接口、被观察者(主题)接口
    • 分别实现这两个接口——订单付款主题,返现观察者,发送信息观察者等等...
    • 创建订单付款后处理器,可交由Spring管理,通过配置文件配置观察者向主题进行注册
    • 在原订单付款后方法中,掉用处理器方法,让主题发出通知,各观察者接收通知执行各自逻辑
代码:
/**
 * 主题
 */
public interface Subject<T> {
    /**
     * 观察者注册
     * @param o
     */
    void registerObserver(Observer o);

    /**
     * 观察者退出
     * @param o
     */
    void removeObserver(Observer o);

    /**
     * 发出通知
     * @param t
     */
    void notifyObservers(T t);
}

/**
 * 订单支付 主题
 **/
public class OrderPaidSubject implements Subject<Order> {
    /**
     * 观察者名单
     */
    private ArrayList<Observer> observerList;

    public OrderPaidSubject() {
        observerList = new ArrayList<>();
    }

    @Override
    public void registerObserver(Observer o) {
        observerList.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        observerList.remove(o);
    }

    /**
     * 遍历观察者名单发送通知
     * @param order
     */
    @Override
    public void notifyObservers(Order order) {
        observerList.forEach(observer -> observer.update(order));
    }
}

/**
 * 观察者
 */
public interface Observer<T> {
    /**
     * 接收通知
     */
    void update(T t);
}

/**
 * 返现观察者
 **/
public class CashBackOB implements Observer<Order> {
    @Override
    public void update(Order order) {
        System.out.println("返现5元,订单编号:" + order.getOrderNo());
    }
}

/**
 * 发送短信观察者
 **/
public class SendMsgOB implements Observer<Order> {
    @Override
    public void update(Order order) {
        System.out.println("发送短信,订单编号:" + order.getOrderNo());
    }
}

/**
 * 订单
 **/
@Data
public class Order {
    private Integer orderId;
    private String orderNo;
}

/**
 * 订单支付后处理
 **/
public class OrderPaidHandler {

    private OrderPaidSubject orderPaidSubject;

    public OrderPaidHandler() {
        orderPaidSubject = new OrderPaidSubject();
        // 可改造为 通过配置文件 注册
        orderPaidSubject.registerObserver(new CashBackOB());
        orderPaidSubject.registerObserver(new SendMsgOB());
    }

    public void orderIsPaid(Order order) {
        orderPaidSubject.notifyObservers(order);
    }
}

/**
 * 测试类
 **/
public class Test {
    public static void main(String[] args) {
        OrderPaidHandler orderPaidHandler = new OrderPaidHandler();
        Order order = new Order();
        order.setOrderId(1);
        order.setOrderNo("01012254");
        orderPaidHandler.orderIsPaid(order);
    }
}

结果:
    返现5元,订单编号:01012254
    发送短信,订单编号:01012254