观察者模式 -- 设计模式系列文章(二)
- 概述
在日常开发工作中,适当的使用一些设计模式,可以让代码扩展性更强,能更好地拥抱变化,让代码更加优雅。本文主要介绍设计模式中的观察者模式,并附上测试示例 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); } }