美文网首页
设计模式——观察者模式

设计模式——观察者模式

作者: prik丶 | 来源:发表于2019-07-25 14:22 被阅读0次

    《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
    

    相关文章

      网友评论

          本文标题:设计模式——观察者模式

          本文链接:https://www.haomeiwen.com/subject/zglhrctx.html