Java观察者设计模式在项目中的应用

本文介绍了观察者设计模式的基本概念及其在工作流管理系统中的应用,展示了如何通过Java代码实现,强调了模式如何提高代码的可读性、复用性和系统解耦。
摘要由CSDN通过智能技术生成

观察者设计模式

观察者设计模式的介绍

观察者设计模式是一种行为型设计模式,用于定义对象之间的一对多依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于事件处理系统或者需要实现发布-订阅机制的情况下。
在观察者模式中,有两类主要角色:
Subject(主题):也称为被观察者,它维护一组依赖于它的观察者对象,并在自身状态发生变化时通知这些观察者。
Observer(观察者):观察者订阅主题的变化,当主题的状态发生变化时,观察者会收到相应的通知,并执行相应的操作。

典型的观察者模式实现包括:
注册和移除观察者:主题对象可以允许观察者订阅或取消订阅。
通知观察者:当主题对象状态发生变化时,通知所有注册的观察者。
更新观察者状态:观察者接收到通知后,执行相应的操作以更新自身状态。

项目应用背景

在一个工作流管理系统中,在子节点开启前,结束前结束后都会触发特定的方法。当只有一个业务单据的时候可以直接在监听类Listener中增添特定的执行逻辑。但是当业务单据多时,每一个单据在增加执行逻辑都需要修改监听类,该监听类耦合性性增加,不便于阅读跟后续的修改。

引入观察者设计模式

  1. 代码可读性和可维护性:
    使用观察者设计模式可以将代码分解为更小的、更具可管理性的模块,主题对象和观察者对象之间的职责清晰分离。这种分离使得代码更易于理解和维护,每个类都只需关注自己的特定任务,而不必关心其他类的实现细节。
    通过将观察者对象的具体逻辑封装在单独的类中,使得代码更具可读性。开发人员可以更轻松地理解每个观察者对象所负责的功能,从而更容易调试和修改代码。
  2. 代码复用性和可扩展性:
    观察者设计模式提高了代码的复用性。由于主题对象和观察者对象之间的松耦合关系,可以轻松地添加新的观察者对象而无需修改主题对象的代码。这样一来,系统具有更高的可扩展性,可以根据需要动态地添加或删除观察者对象,而不会影响到其他部分的代码。
    观察者模式还支持多播机制,一个主题对象的状态变化可以同时通知多个观察者对象。这种机制使得系统更具灵活性,能够满足不同场景下的需求,而无需大规模修改现有代码。
  3. 系统的解耦和降低复杂性:
    观察者设计模式将主题对象和观察者对象解耦,使得它们之间的依赖关系降低到最低限度。主题对象不需要了解观察者对象的具体实现,只需要维护一个观察者列表,并在状态变化时通知这些观察者即可。这种解耦有助于降低系统的复杂性,使得系统更易于理解和维护。

UML 图表

可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:

Subject
+attach(observer: Observer)
+detach(observer: Observer)
+notify()
ConcreteSubject
- state: int
+getState()
+setState(state: int)
+notifyObservers()
Observer
+update()
ConcreteObserver
- observerState: int
+update()

这段Java代码实现了提供的UML图中的观察者设计模式。主题类 ConcreteSubject 实现了主题接口 Subject,负责管理观察者对象并在状态变化时通知它们。观察者类 ConcreteObserver 实现了观察者接口 Observer,定义了具体的更新逻辑。

实际代码实现

下面展示代码逻辑 代码实现

public class BillWorkflowListener extends CommonWorkflowListener {

    private final ObjectProvider<CustomBillWorkflowListener> customWorkflowListeners;

    public XnkBillWorkflowListener(ObjectProvider<CustomBillWorkflowListener> listeners) {
        this.customWorkflowListeners = listeners;
    }

    /**
     * 提交前
     */
    @Override
    public void beforeProcessStart(WorkflowEvent event) {
        super.beforeProcessStart(event);
        performCustomListener("beforeProcessStart", event,
                listener -> listener.beforeProcessStart(event));
    }

    /**
     * 提交后
     */
    @Override
    public void afterProcessStart(WorkflowEvent event) {
        super.afterProcessStart(event);
        performCustomListener("afterProcessStart", event,
                listener -> listener.afterProcessStart(event));
    }

    /**
     * 流程终止(提交取回)
     */
    @Override
    public void afterProcessAbort(WorkflowEvent event) {
        super.afterProcessAbort(event);
        performCustomListener("afterProcessAbort", event,
                listener -> listener.afterProcessAbort(event));
    }

    /**
     * 流程节点动作
     */
    @Override
    public void onBeforeNodeLeft(WorkflowNodeEvent event) {
        super.onBeforeNodeLeft(event);
        performCustomListener("onBeforeNodeLeft", event,
                listener -> listener.onBeforeNodeLeft(event));
    }

    /**
     * 流程结束(通过)
     */
    @Override
    protected void onApproved(WorkflowEvent event, Bill bill) {
        super.onApproved(event, bill);
        performCustomListener("onApproved", event,
                listener -> listener.onApproved(event, bill));
    }

    /**
     * 流程结束(驳回)
     */
    @Override
    protected void onRejected(WorkflowEvent event, Bill bill) {
        super.onRejected(event, bill);
        performCustomListener("onRejected", event,
                listener -> listener.onRejected(event, bill));
    }
    
	/**
	 * 当前节点触发,还没有开始做业务处理之前
	 */
    @Override
	public void onBeforeNodeTriggered(WorkflowNodeEvent event) {
    	 super.onBeforeNodeTriggered(event);
         performCustomListener("onBeforeNodeTriggered", event,
                 listener -> listener.onBeforeNodeTriggered(event));
	}

    /**
     *  当前节点触发,生成UserTask之后触发
     */
    @Override
    public void onAfterNodeTriggered(WorkflowNodeEvent event) {
        super.onAfterNodeTriggered(event);
        performCustomListener("onBeforeNodeLeft", event,
                listener -> listener.onAfterNodeTriggered(event));
    }

    private void performCustomListener(String method, WorkflowEvent e, Consumer<CustomBillWorkflowListener> c) {
        customWorkflowListeners.forEach(l -> {
            if (l.supportByEvent(e)) {
                log.info("Invoke method '{}', customBillWorkflowListener={}, workflowName={}, bizName={}, bizObjId={}",
                        method, l.getClass().getSimpleName(), e.getWorkflowName(), e.getBizName(), e.getBizObjId());
                // Invoke method
                c.accept(l);
            }
            // Skipp
            else {
                log.info("Skipped invoke method '{}', customBillWorkflowListener={}, workflowName={}, bizName={}, bizObjId={}",
                        method, l.getClass().getSimpleName(), e.getWorkflowName(), e.getBizName(), e.getBizObjId());
            }
        });
    }
public interface CustomBillWorkflowListener extends Ordered {

    @Override
    default int getOrder() {
        return LOWEST_PRECEDENCE;
    }

    /**
     * 根据工作流事件确定此监听器是否支持
     *
     * @param event 工作流事件
     */
    boolean supportByEvent(WorkflowEvent event);

    /**
     * 提交前
     */
    default void beforeProcessStart(WorkflowEvent event) {
    }

    /**
     * 提交后
     */
    default void afterProcessStart(WorkflowEvent event) {
    }

    /**
     * 流程终止(提交取回)
     */
    default void afterProcessAbort(WorkflowEvent event) {
    }

    /**
     * 流程节点动作
     */
    default void onBeforeNodeLeft(WorkflowNodeEvent event) {
    }

    /**
     * 流程结束(通过)
     */
    default void onApproved(WorkflowEvent event, Bill bill) {
    }

    /**
     * 流程结束(驳回)
     */
    default void onRejected(WorkflowEvent event, Bill bill) {
    }
    
    /**
	 * 当前节点触发,还没有开始做业务处理之前
	 */
    default void  onBeforeNodeTriggered(WorkflowNodeEvent event) {
    	
    }

    /**
     * 当前节点触发,生成UserTask之后触发
     */
    default void onAfterNodeTriggered(WorkflowNodeEvent event){
    }



    default Bill getBill(WorkflowEvent event) {
        BillDefine define = SpringBeanUtils.getBean(BillDefineService.class).getBillDefine(event.getBizName());
        return SpringBeanUtils.getBean(BillService.class).restoreBill(define, getBillDataObj(event));
    }

    default KObject getBillDataObj(WorkflowEvent event) {
        if (event.getBizObj() != null) {
            return event.getBizObj();
        }
        BillDefine define = SpringBeanUtils.getBean(BillDefineService.class).getBillDefine(event.getBizName());
        KClass clz = define.getDataType();
        return SpringBeanUtils.getBean(BillDataDao.class).get(clz, event.getBizObjId()).createCopy();
    }

}

CustomBillWorkflowListener接口和BillWorkflowListener类结合使用了观察者模式。观察者模式是一种行为设计模式,其中一个对象(称为主题)维护一系列依赖于它的对象(称为观察者),当主题发生变化时,它会通知所有的观察者进行相应的处理。

具体来说:

  • CustomBillWorkflowListener接口定义了一系列的观察者方法,用于处理不同的工作流事件。
  • BillWorkflowListener类作为主题,实现了这些观察者方法,并在各个事件点调用CustomBillWorkflowListener接口中对应的方法。
  • BillWorkflowListener类内部维护了一个customWorkflowListeners,用于存储所有的CustomBillWorkflowListener实例。
  • 在BillWorkflowListener类中,通过performCustomListener方法遍历customWorkflowListeners,找到支持当前事件的CustomBillWorkflowListener实例,并调用其方法来处理相应的事件。

通过观察者模式,BillWorkflowListener类和CustomBillWorkflowListener接口之间实现了解耦,BillWorkflowListener作为主题可以根据需要通知不同的观察者来处理工作流事件,同时也允许新增或移除观察者而不需要修改主题代码。

代码补充

在上一标题代码实现中BillWorkflowListener使用到了Consumer类来简化代码的编写,还可以使用反射的形式来实现,代码如下:

public class BillWorkflowListenerInvoker extends CommonBillWorkflowListener {
    
    // 反射调用CustomBillWorkflowListener方法
    private void invokeCustomListeners(String methodName, WorkflowEvent event) {
        List<CustomBillWorkflowListener> listeners = getCustomListeners();
        // 遍历并调用监听器方法
        for (CustomBillWorkflowListener listener : listeners) {
            if (listener.supportByEvent(event)) {
                invokeMethod(listener, methodName, event);
            }
        }
    }
    
    // 获取所有CustomBillWorkflowListener的实例
    private List<CustomBillWorkflowListener> getCustomListeners() {
        List<CustomBillWorkflowListener> listeners = new ArrayList<>();
        return listeners;
    }
    
    // 反射调用方法
    private void invokeMethod(CustomBillWorkflowListener listener, String methodName, WorkflowEvent event) {
        try {
            Method method = listener.getClass().getMethod(methodName, WorkflowEvent.class);
            method.invoke(listener, event);
        } catch (Exception e) {
            // 处理异常
            e.printStackTrace();
        }
    }

    /**
     * 提交前
     */
    @Override
    public void beforeProcessStart(WorkflowEvent event) {
        super.beforeProcessStart(event);
        invokeCustomListeners("beforeProcessStart", event);
    }

    /**
     * 提交后
     */
    @Override
    public void afterProcessStart(WorkflowEvent event) {
        super.afterProcessStart(event);
        invokeCustomListeners("afterProcessStart", event);
    }


}
  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值