设计模式的使用——模板方法模式+动态代理模式

这篇具有很好参考价值的文章主要介绍了设计模式的使用——模板方法模式+动态代理模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、需求介绍

  现有自己写的的一套审批流程逻辑,由于代码重构,需要把以前的很多业务加上审批的功能,再执行完审批与原有业务之后,生成一个任务,然后再统一处理一个任务(本来是通过数据库作业去处理的,后来说这个任务要马上去处理,只能去统一添加一个处理任务的逻辑,去手动触发作业,心里1w只草泥马在欢快的奔腾着)。现有的问题是:

  • 如何将原有的业务逻辑和审批流程给统一整合,以减少工作量
  • 如何统一添加处理任务的功能

二、设计模式选择

  • 模板方法(Template Method)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。我们可以根据这个模式去统一整合业务逻辑和审批流程,将整合的逻辑模板里面。
  • 动态代理()模式:通过动态代理模式对生成任务的方法统一增强,在生成这个任务之后,立马去执行这个任务。

三、代码实现

1、准备工作

项目的目录结构如下:

设计模式的使用——模板方法模式+动态代理模式,设计模式,设计模式

在开始之前,需要规范一些常量

  • 成功状态表示枚举类:
public enum CommonResult {
    SUCCESS("200", "success","成功","成功"),
    FAIL("201","fail","失败","失败");

    private final String code;
    private final String status;
    private final String msg;
    private final String data;

    CommonResult(String code, String status, String msg, String data) {
        this.code = code;
        this.status = status;
        this.msg = msg;
        this.data = data;
    }

    public String getCode() {
        return code;
    }

    public String getStatus() {
        return status;
    }

    public String getMsg() {
        return msg;
    }

    public String getData() {
        return data;
    }

}

  • 新建审批异常类:
public class ApproveException extends RuntimeException {
    public ApproveException(String message){
        super(message);
    }
    public ApproveException(Throwable throwable){
        super(throwable);
    }
}

  • 新建常量类,表示不同审批结果,不同审批返回值需要处理不同的业务逻辑:
public interface Constants {
    //不执行插入任务 与 执行任务的逻辑
    String FLOW_STATUS1 = "1";
    //只执行审批逻辑
    String FLOW_STATUS2 = "2";
    //不执行业务逻辑
    String FLOW_STATUS3 = "3";
    //执行所有逻辑
    String FLOW_STATUS4 = "4";
}

  • 封装审批参数类,用来规范审批值传递,通过这个类规定需要审批接口需要的参数:

/**
 * @description: 请求审批
 * @create: 2020-04-24 13:40
 **/
public class ApproveDTO {
    //审批意见
    private String suggestion;
    //0 驳回 1 同意
    private Integer appType;
    //流程id
    private Integer approveId;
    //当前员工id
    private String empId;
    //当前员工name
    private String empName;
    //当前角色ID
    private String roleId;

    public String getSuggestion() {
        return suggestion;
    }

    public void setSuggestion(String suggestion) {
        this.suggestion = suggestion;
    }

    public Integer getAppType() {
        return appType;
    }

    public void setAppType(Integer appType) {
        this.appType = appType;
    }

    public Integer getApproveId() {
        return approveId;
    }

    public void setApproveId(Integer approveId) {
        this.approveId = approveId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getEmpId() {
        return empId;
    }

    public void setEmpId(String empId) {
        this.empId = empId;
    }

    public String getRoleId() {
        return roleId;
    }

    public void setRoleId(String roleId) {
        this.roleId = roleId;
    }
}

2、编写审批逻辑

  这里只是一个简单地审批服务类,主要有两个功能:
① execApprove()方法:用来执行审批的节点流转等逻辑。
② runApproveTask()方法:这个是后来新加的添加任务后马上执行的需求,主要调用数据库的存储过程。

  • 审批服务接口:
public interface IApproveService {
    /**
     * 执行审批
     * @param approveDTO 审批信息
     * @return 0 失败 1 成功
     */
    String execApprove(ApproveDTO approveDTO, Map<String,String> paramMap);

    /**
     * 执行审批存储过程
     */
    void runApproveTask(Integer approveId);
}
```java
- 审批服务接口实现类
```java
public class ApproveServiceImpl implements IApproveService {
    @Override
    public String execApprove(ApproveDTO approveDTO, Map<String, String> paramMap) {
        System.out.println(approveDTO.getEmpName()+"执行了"+(approveDTO.getAppType().equals(0)?"驳回":"通过")+"审批流程逻辑,因为:"+approveDTO.getSuggestion());
        return paramMap.get("logic");
    }

    @Override
    public void runApproveTask(Integer approveId) {
        System.out.println("存储过程被执行......");
    }
}
3、封装审批模板

  这里主要处理业务逻辑和审批逻辑之间的关系:

  • 抽象类,主要定义了钩子方法要实现的功能,doApprove()方法:执行审批,处理业务逻辑和审批逻辑之间的关系就是这个方法:
public interface IApproveTemplate {

    String doApprove();

}
  • 模板类,通用模板逻辑封装,扩展需要在业务逻辑中实现的功能(抽象方法),实现了IApproveTemplate的doApprove()方法(钩子方法):
/**
 * @author FluffyCatkin
 * @create: 2020-06-02 14:00
 **/
public abstract class CommonApproveTemplate implements IApproveTemplate {

    protected IApproveService approveService;
    protected ApproveDTO approveDTO;
    private final Map<String,String> paramMap;
    public CommonApproveTemplate(ApproveDTO approveDTO, Map<String,String> paramMap) {
        this.approveDTO = approveDTO;
        this.paramMap = paramMap;
        this.approveService = new ApproveServiceImpl();
        this.approveService = new ApproveServiceImpl();
    }
    @Override
    public String doApprove(){
        String execResult = execApprove();
        String businessResult = "";
        //执行自定义业务
        if (Objects.equals(execResult,Constants.FLOW_STATUS1)||Objects.equals(execResult,Constants.FLOW_STATUS4)){
            businessResult = business();
            if (!businessResult.equals(CommonResult.SUCCESS.getStatus())){
                System.out.println("审批流程执行失败,开始回滚");
            }
        }

        //插入任务
        if (Objects.equals(execResult,Constants.FLOW_STATUS3)||Objects.equals(execResult,Constants.FLOW_STATUS4)){
            businessResult = taskBusiness();
            if (!businessResult.equals(CommonResult.SUCCESS.getStatus())){
                System.out.println("审批流程执行失败,开始回滚");
            }
        }
        //什么也不做
        if (Objects.equals(execResult,Constants.FLOW_STATUS2)){
            return CommonResult.SUCCESS.getStatus();
        }
        return businessResult;
    }

    /**
     * 执行审批流程节点流转逻辑
     * @return 不同的执行结果
     * 比如所有人审批通过或者流转到下一个审批人等等,这里不纠结具体 只用 1 2 3 4表示不同结果
     */
    private String execApprove(){
        return approveService.execApprove(this.approveDTO,this.paramMap);
    }

    /**
     * 对传的审批参数进行解析校验,可以判断调用通过业务逻辑还是 拒绝的业务逻辑等等
     */
    protected abstract String business();

    /**
     * 新增任务,不同的业务需要自定义自己的任务
     */
    protected abstract String taskBusiness();

}
  • 业务逻辑抽象类,定义了用户需要在自己的业务服务类中所实现的功能,这些功能不同的业务是不一样的:

public interface CommonApproveService {
    /**
     * 跟进审批同意操作
     * @param paramMap 参数
     */
   String agreeApprove(Map<String, String> paramMap);

    /**
     * 跟进审批拒绝操作
     * @param paramMap 参数
     */
    String refuseApprove(Map<String, String> paramMap);

    /**
     * 将审批操作放到任务中跑
     * @param paramMap 审批参数
     */
     String insertApproveTask(Map<String, String> paramMap,Integer approveId);

    /**
     * 执行跟进的审批
     * @param approveDTO 审批流程改变需要的参数
     * @param paramMap 执行业务逻辑需要的参数
     * @return 审批结果
     */
    String execApprove(CommonApproveService service,ApproveDTO approveDTO, Map<String, String> paramMap);

}
  • 模板具体实现类,这里封装了用户定义的业务的通用服务类,这些服务类要统一实现上面的CommonApproveService接口:

/**
 * @author FluffyCatkin
 * @create: 2020-06-02 14:26
 **/

public class ApproveConcrete<T extends CommonApproveService> extends CommonApproveTemplate {
    private final T service;
    private final Map<String, String> paramMap;
    public ApproveConcrete(ApproveDTO approveDTO, Map<String, String> paramMap, T service) {
        super(approveDTO, paramMap);
        this.service = service;
        this.paramMap = paramMap;
    }

    @Override
    protected String business() {
        if(super.approveDTO==null){
            throw new ApproveException("审批失败,没有参数!");
        }
        Integer appType = super.approveDTO.getAppType();
        if (appType==null){
            throw new ApproveException("审批失败,未传入审批意见,请传入:1 同意  0 驳回!");
        }
        if (appType==0){
            return service.refuseApprove(paramMap);
        }
        if (appType==1){
            return service.agreeApprove(paramMap);
        }
        throw new ApproveException("审批失败,审批意见错误,请传入:1 同意  0 驳回!");
    }

    @Override
    protected String taskBusiness() {
        if(super.approveDTO==null){
            throw new ApproveException("审批失败,没有参数!");
        }
        return service.insertApproveTask(paramMap,approveDTO.getApproveId());
    }


}

4、业务逻辑服务实现

  • 定义服务接口,要继承封装的业务逻辑抽象类
public interface IBusinessService extends CommonApproveService {
  //在这里可以写业务逻辑相关方法
}
  • 定义服务接口实现类

public class BusinessServiceImpl implements IBusinessService {
    @Override
    public String agreeApprove(Map<String, String> paramMap) {
        System.out.println("执行同意业务逻辑");
        return CommonResult.SUCCESS.getStatus();
    }

    @Override
    public String refuseApprove(Map<String, String> paramMap) {
        System.out.println("执行拒绝业务逻辑");
        return CommonResult.SUCCESS.getStatus();
    }

    @Override
    public String insertApproveTask(Map<String, String> paramMap, Integer approveId) {
        System.out.println("执行插入任务业务逻辑");
        return CommonResult.SUCCESS.getStatus();
    }

    @Override
    public String execApprove(CommonApproveService service,ApproveDTO approveDTO, Map<String, String> paramMap) {
        System.out.println("开始执行审批....");
        return new ApproveUtil<> (service).execApprove(approveDTO, paramMap);
    }
}
5、通过动态代理对业务逻辑服务类进行增强,加上立刻执行存储过程的逻辑:
  • 代理类:

/**
 * @author FluffyCatkin
 * @version 1.0
 * @date 2020/1/3 0003 10:04
 * @description (动态代理)代理(Proxy)类:对真实主题功能的扩展
 */
public class DynamicProxy implements InvocationHandler {
    //需要代理的对象
    private final Object  dynamicSubject;
    private final IApproveService approveService = new ApproveServiceImpl();
    private static final String  PROXY_METHOD = "insertApproveTask";
    /**
     * 构造方法
     * @param dynamicSubject 要代理的对象
     */
    public DynamicProxy(Object dynamicSubject){
        this.dynamicSubject = dynamicSubject;
    }

    /**
     *
     * @param proxy 被代理的类
     * @param method 要增强的方法
     * @param args 增强的方法参数
     * @return 增强的方法返回值
     * @throws Throwable 异常
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object invoke = method.invoke(dynamicSubject, args);
        if (PROXY_METHOD.equals(method.getName())){
            approveService.runApproveTask(null);
        }
        return invoke;
    }

    /**
     * 获取被代理的对象
     * @return 被代理的对象
     */
    public Object getCommonApproveService() {
        return dynamicSubject;
    }

    /**
     * 获取代理后增强的对象
     * @param dynamicSubject 被代理的对象
     * @return 代理后增强的对象
     */
    public static  CommonApproveService newInstance(Object dynamicSubject) {
        InvocationHandler invocationHandler = new DynamicProxy(dynamicSubject);
        return (CommonApproveService) Proxy.newProxyInstance(dynamicSubject.getClass().getClassLoader(),
                dynamicSubject.getClass().getInterfaces(),invocationHandler);
    }
}
6、测试

public class MainTest {

    //对业务的服务类进行增强,在spring中,可以通过spring配置,获取所有CommonApproveService的子类,并统一进行增强
    //然后通过@Autowired注解直接拿到增强对的服务类
    private final CommonApproveService businessService = DynamicProxy.newInstance(new BusinessServiceImpl());

    @Test
    public void testPassApprove() {
        ApproveDTO approveDTO = new ApproveDTO();
        approveDTO.setAppType(1);
        approveDTO.setEmpName("张三");
        approveDTO.setSuggestion("你长得太好看了");
        //这里是业务执行需要的参数,不同的业务需要不同的参数,这里使用map封装
        Map<String, String> paramMap = new HashMap<>();
        //通过这里指定审批流程的流转结果,从而控制其流转到不同的业务逻辑里,实际情况是根据审批节点流转结果判断的
//        paramMap.put("logic", Constants.FLOW_STATUS1);
//        paramMap.put("logic", Constants.FLOW_STATUS2);
//        paramMap.put("logic", Constants.FLOW_STATUS3);
        paramMap.put("logic", Constants.FLOW_STATUS4);
        String res = businessService.execApprove(businessService, approveDTO, paramMap);
        System.out.println(res);
    }
}

执行结果:
设计模式的使用——模板方法模式+动态代理模式,设计模式,设计模式

  注意:这里简化了很多逻辑,也可以结合项目进行改造,比如:可以在spring中,可以通过spring配置,获取所有CommonApproveService的子类,并统一进行增强,然后通过@Autowired注解直接拿到增强对的服务类。文章来源地址https://www.toymoban.com/news/detail-686371.html

到了这里,关于设计模式的使用——模板方法模式+动态代理模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用Servlet完成单表的增删改查功能以及使用模板方法设计模式解决类爆炸问题(重写service模板方法)

    开发前的准备 导入sql脚本创建一张部门表 通过绑定属性资源配置文件的方式创建JDBC的工具类utils/DBUtil 分析系统的功能: 只要这个操作连接了数据库,就表示一个独立的功能 查看部门列表 , 新增部门 , 删除部门 , 查看部门详细信息 , 跳转到修改页面(动态的从数据库中获取信

    2024年02月10日
    浏览(46)
  • 3.设计模式之后七种模式桥接装饰者组合外观享元代理模板

    1.桥接模式 bridge(抽象类的实现的子类,通过聚合间接调用接口方法 就是桥) 实现和抽象分开,使他可以独立改变 结构型设计模式 基于类的最小设计原则(增加功能,增加最少个数的类),通过封装 聚合和继承让不同类实现不同职责 图 23桥接模式原理图 图 26桥接模式传统解决手机操

    2024年02月12日
    浏览(52)
  • 设计模式 代理模式(静态代理 动态代理) 与 Spring Aop源码分析 具体是如何创建Aop代理的

    代理模式是一种结构型设计模式,它通过创建一个代理对象来控制对真实对象的访问。这种模式可以用于提供额外的功能操作,或者扩展目标对象的功能。 在代理模式中,代理对象与真实对象实现相同的接口,以便在任何地方都可以使用相同的接口来调用真实对象的方法。这

    2024年01月20日
    浏览(44)
  • 【Java基础教程】(十五)面向对象篇 · 第九讲:抽象类和接口——定义、限制与应用的细节,初窥模板设计模式、工厂设计模式与代理设计模式~

    掌握 抽象类和接口的定义、使用、区别、常见设计模式; 抽象类是代码开发中的重要组成部分,利用抽象类可以明确地定义子类需要覆写的方法,这样相当于在语法程度上对子类进行了严格的定义限制,代码的开发也就更加标准。下面具体介绍抽象类的概念。 普通类可以直

    2024年02月16日
    浏览(48)
  • 设计模式——模板方法模式

    模板方法模式(Template Method Pattern)是一种行为型设计模式,它在抽象类中定义了一个算法的框架,并将一些步骤延迟到子类中实现。这种模式使得子类可以在不改变算法结构的情况下重写算法中的某些特定步骤。 抽象模板类(Abstract Template Class): 定义一个操作中的算法骨架

    2024年01月17日
    浏览(47)
  • 【设计模式】模板方法模式

    模板方法模式:定义一个操作中的算法骨架(父类),而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算法的结构来重定义该算法的 实现一些操作时,整体步骤很固定,但是呢。就是其中一小部分需要改变,这时候可以使用模板方法模式,将容易变的部分抽

    2024年02月08日
    浏览(47)
  • 设计模式—模板方法模式

    定义一个操作的流程框架,而将流程中一些步骤延迟到子类中实现。使得子类在不改变流程结构的情况下,重新定义流程中的特定步骤。 主要角色: 抽象类: 负责给出操作流程的轮廓或框架,由模板方法和若干基本方法组成。   1、抽象方法:由抽象类声明,在具体子类中实

    2024年02月10日
    浏览(50)
  • 设计模式---模板方法模式

            所谓模板方法模式,就是提供一种方法的模板来实现一种规范,其他人可以利用这个模板定义自己的逻辑。         在Java编程中的应用,主要就是通过接口或者抽象类来实现的,抽象类中可以把逻辑函数声明为final类型,表示不能被重写,即不能改变逻辑。在接口中

    2024年04月24日
    浏览(44)
  • 设计模式(13):模板方法模式

    实现一个功能时,整体步骤很固定,但是,某些部分易变。易变部分可以抽象出来,供子类实现。 非常繁琐,各个框架,类库中都有它的影子,比如常见的有: 数据库访问的封装 Junit单元测试 servlet中关于doGet/doPost方法调用 spring框架中各种Template shire中权限认证和授权都用到

    2024年04月16日
    浏览(47)
  • 设计模式(7)模板方法模式

    一、定义: 定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。

    2024年02月12日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包