zoukankan      html  css  js  c++  java
  • 观察者模式 -- 设计模式系列文章(二)

    • 概述

      在日常开发工作中,适当的使用一些设计模式,可以让代码扩展性更强,能更好地拥抱变化,让代码更加优雅。本文主要介绍设计模式中的观察者模式,并附上测试示例 Demo 供大家参考。

    • 定义

      观察者模式定义了对象之间一对多的依赖关系(一的一方为被观察者,多的一方为观察者),当被观察者状态发生变化时,所有的观察者能够及时收到通知,并做出相应的动作。

    • 个人理解

      观察者模式,主要应用在多个附属业务依赖主业务的场景,附属业务需要依赖主业务的执行结果,且主业务不需要等待附属业务的返回结果。通过观察者模式的应用,可以降低主业务与附属业务之间的耦合度,同时也提高了附属业务的可扩展性和灵活性,可根据实际情况,在运行时,动态追加附属业务或移除部分附属业务。

    • 示例介绍

      这里,我以电商系统中,比较常用的退货功能模块为例子来描述观察者模式。目前大多数电商平台都承诺7天无理由退货,在退货的过程中会涉及到很多业务逻辑的处理,比如资产退还(包括在线支付和平台资产)、积分扣减(购买商品获得积分)、修改库存,而平台资产又包含预存款、购物券、礼品卡等等。这里我们简单举例,以退还在线支付的金额和积分扣减为例。在整个主要的退货逻辑完成后,得到需要退还的金额和需要扣减的积分,把货款原路返还给用户,同时把购买商品时赠送的积分扣减,其中主要的退货逻辑就是主要业务,即被观察者,货款原路返还和积分扣减就是附属业务,即观察者。UML 图如下:

      从上面的 UML 图可以看出,被观察者需要实现 ISubject 接口,观察者需要实现 IObserver 接口。在被观察者对象中,用一个集合存放所有已经注册的观察者,并且通过 registerObserver 或 removeObserver 方法实现观察者的注册或移除,通过 notifyAllObserver 方法给所有已注册的观察者推消息。在观察者对象中,通过 register 和 remove 方法把观察者自己注册到被观察者或从被观察者中移除,通过 update 方法接收来自被观察者的消息,后续如果还需要处理其他的附属业务,只需要添加对应的观察者并注册到被观察者对象中即可,从而达到在运行时动态调整业务的效果。

    •  示例代码

       ISubject 被观察者接口(主业务接口)

    package observer;
    
    public interface ISubject {
        public void registerObserver(IObserver observer);
        public void removeObserver(IObserver observer);
        public void notifyAllObserver();
    }

      IObserver 观察者接口(附属业务接口)

    package observer;
    
    public interface IObserver {
        public void update(String info);
        public void remove();
        public void register();
    }

      ReturnOrder 被观察者实体类(主业务实体类)

    package observer;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class ReturnOrder implements ISubject {
        private List<IObserver> observerList = new ArrayList<IObserver>();
    
        public ReturnOrder() {
            // TODO Auto-generated constructor stub
        }
    
        @Override
        public void registerObserver(IObserver observer) {
            if(observerList.indexOf(observer)==-1){
                observerList.add(observer);
                System.out.println("添加观察者成功...");
            }
        }
    
        @Override
        public void removeObserver(IObserver observer) {
            int index = observerList.indexOf(observer);
            if(index>=0){
                observerList.remove(index);
                System.out.println("移除观察者成功...");
            }
        }
    
        @Override
        public void notifyAllObserver() {
            for(IObserver observer : observerList){
                observer.update("订单1001");
            }
        }
    }

      IntegralObserver 观察者实体类(积分扣减业务实体类)

    package observer;
    
    public class IntegralObserver implements IObserver {
        private ISubject returnOrder;
    
        public IntegralObserver(ISubject returnOrder) {
            this.returnOrder = returnOrder;
        }
    
        @Override
        public void update(String info) {
            System.out.println(info + "扣减积分...");
        }
    
        @Override
        public void remove() {
            returnOrder.removeObserver(this);
        }
    
        @Override
        public void register() {
            returnOrder.registerObserver(this);
        }
    
        public ISubject getReturnOrder() {
            return returnOrder;
        }
    
        public void setReturnOrder(ISubject returnOrder) {
            this.returnOrder = returnOrder;
        }
    }

      RefundObserver 观察者实体类(退款业务实体类)

    package observer;
    
    public class RefundObserver implements IObserver {
        private ISubject returnOrder;
    
        public RefundObserver(ISubject returnOrder) {
            this.returnOrder = returnOrder;
        }
    
        @Override
        public void update(String info) {
            System.out.println(info + "退还货款...");
        }
    
        @Override
        public void remove() {
            returnOrder.removeObserver(this);
        }
    
        @Override
        public void register() {
            returnOrder.registerObserver(this);
        }
    
        public ISubject getReturnOrder() {
            return returnOrder;
        }
    
        public void setReturnOrder(ISubject returnOrder) {
            this.returnOrder = returnOrder;
        }
    }

      TestMain 测试类

    package test;
    
    import observer.IntegralObserver;
    import observer.RefundObserver;
    import observer.ReturnOrder;
    
    public class TestMain {
    
        public static void main(String[] args) {
            ReturnOrder returnOrder = new ReturnOrder();
            IntegralObserver integralObserver = new IntegralObserver(returnOrder);
            integralObserver.register();
            RefundObserver refundObserver = new RefundObserver(returnOrder);
            refundObserver.register();
    
            returnOrder.notifyAllObserver();
            returnOrder.removeObserver(refundObserver);
            returnOrder.registerObserver(refundObserver);
        }
    
    }

    欢迎转载,转载必须标明出处 

  • 相关阅读:
    游标本次循环,跳过某些语句
    SQL 把结果集的某列连加成一行
    DotNetty 跨平台的网络通信库(转)
    Slickflow.NET 开源工作流引擎基础介绍-.NET Core2.0 版本实现介绍 (转)
    C# Winform应用程序占用内存较大解决方法整理(转)
    (转)vs2010 vs2013等vs中如何统计整个项目的代码行数
    如何将运维的报警做成运营的报警--Java后端架构
    阿里员工内部常用免费工具包 (转)
    ASP.NET中常用的几个李天平开源公共类LTP.Common,Maticsoft.DBUtility,LtpPageControl (转)
    C#与MATLAB混合编程
  • 原文地址:https://www.cnblogs.com/rexfang/p/6702035.html
Copyright © 2011-2022 走看看