设计模式——模板方法的一个应用

本文深入探讨了模板方法设计模式的应用,特别是在业务处理流程中的作用。通过定义一系列固定的步骤,如前置校验、业务处理、后置处理及最终操作,实现了代码的结构化和模块化。文章提供了一个通用的处理器抽象类示例,并详细解释了如何使用和扩展此模板。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模板方法

模板方法

很多情况下代码中的业务都可以抽象出一个模板去解决,这时候经常需要用到模板方法。大家经常接触到的是一些业务方法的抽象模板,比如在计算优惠券的流程当中总是有一定的步骤:

(1)先计算该商品是否可以拥有优惠券信息

(2)再为该商品绑定优惠券信息

(3)最后回调或者通知向下的流程

今天要记录的是一个通用服务层的模板方法,包含了前置校验、后置处理(是有点像拦截器= =)、finally操作。

业务processor

  1. 可以定义一个domainProcessor去代表业务操作的processor接口,这个接口可以承接泛型。
public interface DomainProcessor<T> {

    /**
     * 处理业务的方法 返回值现在是void的 也可以自己定义一个通用的类似于上下文的返回值
     *
     * @param context
     */
    void process(T context);
}

这里承接的泛型context是一个上下文的概念,指的是在一个业务处理processor中的上下文信息,其中可以有计算的参数,计算的结果和一些中间信息。

  1. 做一个抽象类,去将其中的前置操作、biz操作、后置操作、finally操作定义出来。
public abstract class AbstractProcessor<T> implements DomainProcessor<T> {

    /**
     * 前置处理 主要做一些校验逻辑 编排的时候放在前边
     *
     * @param context
     * @return
     */
    protected boolean preHandle(T context){
        return true;
    }

    /**
     * 业务处理 这个是抽象方法 子类去实现具体的逻辑
     * @param context
     */
    protected abstract void bizHandle(T context);

    /**
     * 后置处理
     *
     * @param context
     */
    protected void postHandle(T context) {
    }

    /**
     * last 操作
     * @param context
     */
    protected void finallyHandle(T context) {
    }

    /**
     * 异常处理
     *
     * @param context
     * @param e
     */
    protected void exceptionHandle(T context, Exception e) {
        // TODO 打印error或者warn级别日志
        throw new BizException(e.getMessage(), e);
    }

    @Override
    public void process(T context) {
        /**
         * 编排流程
         */
        try {
            if (!preHandle(context)) {
//                log.warn("处理器前置处理失败,退出。context:{}", context);
                return;
            }
            // 业务方法
            bizHandle(context);
            // 后置操作
            postHandle(context);
        } catch (Exception e) {
            exceptionHandle(context, e);
        } finally {
            finallyHandle(context);
        }
    }

}

可以看到,这里定义了前置操作,这里可以去对biz要用的参数进行一个校验或者一些前置操作,同时将biz定义为了抽象方法,意图在为了让子类去继承时一定要去实现bizHandle这个方法。而exceptionHandle和finallyHandle方法则定义了异常的处理和最终要做的(比如线程快照的清除)。而整个process方法其实就是整个处理器的入口,即对这整个流程的一个编排。

可以看一个这个模板processor的的具体实现和测试类:

public class AbstractProcessorTest {

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void main(String[] args) {
        // TODO test
        TestContext testContext = new TestContext();
        contextHolder.set("aaa");
        TestProcessor testProcessor = new TestProcessor();
        // 调用process的编排
        testProcessor.process(testContext);

        TestContext exContext = new TestContext();
        // test bizHandle
        testProcessor.process(exContext);
    }

    private static class TestProcessor extends AbstractProcessor<TestContext> {
        @Override
        protected boolean preHandle(TestContext context) {
            // 前置的一个check或者一个前置操作
            String s = contextHolder.get();
            if (s == null) {
                throw new RuntimeException("holder中字符串为空");
            }

            context.setMessage(s);
            return true;
        }

        @Override
        protected void postHandle(TestContext context) {
            context.setPostStr("post");
            System.out.println("processor 结果是:"+ context.isResult());
        }

        @Override
        protected void finallyHandle(TestContext context) {
            if (context.isResult()) {
                contextHolder.remove();
            }
        }

        @Override
        protected void bizHandle(TestContext context) {
            context.setResult(context.getMessage().length()>0);
        }
    }
}

总结

这个模板可以作为之后一个处理器的抽象模板,能让代码逻辑很清晰的展现出来,也能解耦了各个处理模块,这里可以总结下。
github地址:
https://github.com/zhanglijun1217/design_mode/tree/master/src/main/java/daily/tools/abstract_template

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值