【设计模式】策略模式在Java工程中应用

简介: 【设计模式】策略模式在Java工程中应用

在之前的文章中,曾经给大家介绍过策略模式:【设计模式】策略模式,在该篇文章中,我们曾很清楚的说到,策略模式主要解决的问题是:在有多种算法相似的情况下,解决使用 if...else 所带来的复杂和难以维护。策略模式使我们的实现更加符合开闭原则:面向扩展开发,面向修改关闭。在后来的学习和工作的多次应用中,有了更加深刻的认识。再次总结此篇文章赘述下。


此篇文章,将以创建订单为例,创建不同类型的订单,不同类型的订单不同的处理逻辑


类图:



image.png


代码:

  1. 抽象策略(Strategy)角色:抽象策略角色由抽象类或接口来承担,它给出具体策略角色需要实现的接口;
package strategyTest;
import strategyTest.dto.BaseRequestDTO;
/**
 * 类 名 称:CreateStrategy
 * 类 描 述:策略抽象类
 * 创建时间:2023/2/20 3:46 下午
 * 创 建 人:admin
 */
public abstract class AbstractOrderStrategy {
    public abstract Boolean isPracticable(BaseRequestDTO dto);
    // 业务执行总流程
    public ResponseResult process(BaseRequestDTO dto) {
        ResponseResult paramsValidate = validateParams(dto);
        if (!paramsValidate.isSuccess()) {
            return paramsValidate;
        }
        ResponseResult ruleValidate = validateRules(dto);
        if (!ruleValidate.isSuccess()) {
            return ruleValidate;
        }
        ResponseResult processResult = doProcess(dto);
        if(processResult.isSuccess()){
            postProcessAction(dto);
        }
        return processResult;
    }
    // 参数校验
    protected abstract ResponseResult validateParams(BaseRequestDTO dto);
    // 业务规则校验
    protected abstract ResponseResult validateRules(BaseRequestDTO dto);
    // 核心实现
    protected abstract ResponseResult doProcess(BaseRequestDTO dto);
    // 后置处理(异步操作等)
    protected abstract void postProcessAction(BaseRequestDTO dto);
}


2.具体策略(ConcreteStrategy)角色:实现封装了具体的算法或行为;

顺风车类型处理:

1. package strategyTest.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import strategyTest.AbstractOrderStrategy;
import strategyTest.ResponseResult;
import strategyTest.dto.BaseRequestDTO;
import strategyTest.dto.SfcRequestDTO;
/**
 * 类 名 称:SfcImpl
 * 类 描 述:TODO
 * 创建时间:2023/2/20 3:58 下午
 * 创 建 人:admin
 */
@Service
public class SfcImpl extends AbstractOrderStrategy {
    private Logger logger = LoggerFactory.getLogger(SfcImpl.class);
    @Override
    public Boolean isPracticable(BaseRequestDTO dto) {
        if(dto.getType() == 1){
            return true;
        }
        return false;
    }
    @Override
    protected ResponseResult validateParams(BaseRequestDTO dto) {
        SfcRequestDTO sfcRequestDTO = (SfcRequestDTO) dto;
        if (sfcRequestDTO.getIsShare() == null || sfcRequestDTO.getIsShare() == 0) return ResponseResult.ERROR;
        logger.info("sfc validateParams success");
        return ResponseResult.SUCCESS;
    }
    @Override
    protected ResponseResult validateRules(BaseRequestDTO dto) {
        // 无校验
        return ResponseResult.SUCCESS;
    }
    @Override
    protected ResponseResult doProcess(BaseRequestDTO dto) {
        logger.info("sfc doProcess success");
        return ResponseResult.SUCCESS;
    }
    @Override
    protected void postProcessAction(BaseRequestDTO dto) {
        logger.info("sfc 异步执行...");
    }
}


巴士订单处理:

package strategyTest.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import strategyTest.AbstractOrderStrategy;
import strategyTest.ResponseResult;
import strategyTest.dto.BaseRequestDTO;
import strategyTest.dto.BusRequestDTO;
/**
 * 类 名 称:BusImpl
 * 类 描 述:TODO
 * 创建时间:2023/2/20 3:58 下午
 * 创 建 人:admin
 */
@Service
public class BusImpl extends AbstractOrderStrategy {
    private Logger logger = LoggerFactory.getLogger(BusImpl.class);
    @Override
    public Boolean isPracticable(BaseRequestDTO dto) {
        if (dto.getType() == 2) {
            return true;
        }
        return false;
    }
    @Override
    protected ResponseResult validateParams(BaseRequestDTO dto) {
        BusRequestDTO busRequestDTO = (BusRequestDTO) dto;
        if (busRequestDTO.getRouteId() == null || busRequestDTO.getRouteId() == 0) return ResponseResult.ERROR;
        logger.info("bus validateParams success");
        return ResponseResult.SUCCESS;
    }
    @Override
    protected ResponseResult validateRules(BaseRequestDTO dto) {
        BusRequestDTO busRequestDTO = (BusRequestDTO) dto;
        if (busRequestDTO.getSeats() != null && busRequestDTO.getSeats() > 30) return ResponseResult.ERROR;
        logger.info("bus validateRules success");
        return ResponseResult.SUCCESS;
    }
    @Override
    protected ResponseResult doProcess(BaseRequestDTO dto) {
        logger.info("bus doProcess success");
        return ResponseResult.SUCCESS;
    }
    @Override
    protected void postProcessAction(BaseRequestDTO dto) {
        logger.info("bus 异步执行...");
    }
}



3.上下文(Context)角色:持有抽象策略类的引用。(引用,执行策略)

package strategyTest;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import strategyTest.dto.BaseRequestDTO;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
 * 类 名 称:StrategyContext
 * 类 描 述:策略执行上下文
 * 创建时间:2023/2/20 3:47 下午
 * 创 建 人:admin
 */
@Component
public class StrategyContext{
    // 策略管理类
    @Autowired
    private List<AbstractOrderStrategy> strategies = new ArrayList<>();
    // 获取策略类
    public AbstractOrderStrategy getStrategy(BaseRequestDTO dto) {
        for (AbstractOrderStrategy strategy : strategies) {
            if (strategy.isPracticable(dto)) {
                return strategy;
            }
        }
        return null;
    }
}




调用方client:

可以在一个controller,也可以写在多个controller

package strategyTest.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import strategyTest.AbstractOrderStrategy;
import strategyTest.ResponseResult;
import strategyTest.StrategyContext;
import strategyTest.dto.BaseRequestDTO;
import strategyTest.dto.BusRequestDTO;
import strategyTest.dto.SfcRequestDTO;
/**
 * 类 名 称:客户端请:可以充当controller或者业务调用上游
 * 类 描 述:TODO
 * 创建时间:2023/2/20 3:58 下午
 * 创 建 人:admin
 */
@RestController
public class ClientTest {
    @Autowired
    private StrategyContext strategyContext;
    @RequestMapping("/createSfc")
    public ResponseResult createSfc(SfcRequestDTO sfcRequestDTO){
        if(sfcRequestDTO == null){
            return ResponseResult.ERROR;
        }
        return this.createOrder(sfcRequestDTO);
    }
    @RequestMapping("/createBus")
    public ResponseResult createBus(BusRequestDTO busRequestDTO){
        if(busRequestDTO == null){
            return ResponseResult.ERROR;
        }
        return this.createOrder(busRequestDTO);
    }
    private ResponseResult createOrder(BaseRequestDTO baseRequestDTO) {
        AbstractOrderStrategy strategy = strategyContext.getStrategy(baseRequestDTO);
        if(strategy == null){
            return ResponseResult.ERROR;
        }
        return strategy.process(baseRequestDTO);
    }
}


我们看下运行结果:

sfc运行结果:


885a4a34877e04fdb4a825e914bfe5a1.png

bus运行结果:


e25202176067c83800f023bf9dda4d0c.png

是不是非常简洁明了!!!


e839a47e643d5973603e66cfa9feba25.png

我们看完代码,再结合类图看下,此时如果我们想新增一种类型的创建订单流程,比如创建一笔代驾订单,需要如何做? 我们只需要做两步:


1、新增一个代驾的实现类DjImpl,继承StrategyContext类;


2、在Controller中,新增一个方法(如果不同类型的订单有不在同一个controller,可将createOrder方法抽象到父类controller,此时新增一个子类controller继承父类和父类的方法即可);


其他地方无需改动。。。其他类型的创建订单流程完全无改动,无影响。下单流程解耦,测试范围极大的降低。


想想我们在项目中,相似的场景写过多少if else。每次添加新的实现,是否影响到原有功能。结合这篇文章,希望能对读者朋友有所帮助。


总结:


策略模式帮助我们把相似的算法抽象,使用上下文管理抽象类的具体实现,每次新增算法时,只需新增具体实现。使我们的代码轻松解耦,符合开闭原则,极大的缩小了影响范围。是成为一名优秀工程师的必修课!

相关文章
|
5天前
|
设计模式 安全 数据库连接
后端开发中的设计模式应用
在软件开发的浩瀚海洋中,设计模式如同灯塔,为后端开发者指引方向。它们不仅仅是代码的模板,更是解决复杂问题的智慧结晶。本文将深入探讨几种常见的设计模式,包括单例模式、工厂模式和观察者模式,并揭示它们在实际应用中如何提升代码的可维护性、扩展性和重用性。通过实例分析,我们将一窥这些模式如何在后端开发中大放异彩,助力构建高效、灵活的软件系统。
|
6天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
|
2天前
|
设计模式 Java
Java设计模式:组合模式的介绍及代码演示
组合模式是一种结构型设计模式,用于将多个对象组织成树形结构,并统一处理所有对象。例如,统计公司总人数时,可先统计各部门人数再求和。该模式包括一个通用接口、表示节点的类及其实现类。通过树形结构和节点的通用方法,组合模式使程序更易扩展和维护。
Java设计模式:组合模式的介绍及代码演示
|
6天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑】设计模式——原型模式
对比原型模式和传统方式的实现思路、代码方案、优缺点,阐述原型模式的使用场景,以及深拷贝、浅拷贝等相关概念,并扩展原型模式在Spring源码中的应用。
【Java笔记+踩坑】设计模式——原型模式
|
1天前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深度解析
在PHP开发中,策略模式是一种行为设计模式,它允许你在运行时根据不同情况选择不同的算法或行为。本文将深入探讨策略模式的定义、结构、使用场景以及在PHP中的实现方法,并通过实例展示如何在PHP项目中应用策略模式来提高代码的灵活性和可维护性。
|
2天前
|
设计模式 人工智能 算法
PHP中的设计模式:策略模式的深入解析与实践软件测试中的人工智能革命:提升效率与准确性的新篇章
在PHP开发中,理解并运用设计模式是提升代码质量和可维护性的重要途径。本文聚焦于策略模式(Strategy Pattern),一种行为型设计模式,它允许在运行时选择算法或业务规则。通过本文,我们将深入探讨策略模式的定义、结构、使用场景以及如何在PHP项目中有效地实现和利用策略模式。不同于性能优化等技术性摘要,本文着重于提供对策略模式全面而实用的理解,助力开发者编写出更加灵活和可扩展的应用程序。 本文深入探讨了人工智能在软件测试领域的应用,揭示了其如何显著提高测试过程的效率和准确性。通过实际案例分析,展示了AI技术在自动化测试、缺陷检测及结果分析中的关键作用,并讨论了实施AI测试策略时面临的挑
12 3
|
1天前
|
Kubernetes Cloud Native Java
探索未来编程新纪元:Quarkus带你秒建高性能Kubernetes原生Java应用,云原生时代的技术狂欢!
Quarkus 是专为 Kubernetes 设计的全栈云原生 Java 框架,凭借其轻量级、快速启动及高效执行特性,在 Java 社区脱颖而出。通过编译时优化与原生镜像支持,Quarkus 提升了应用性能,同时保持了 Java 的熟悉度与灵活性。本文将指导你从创建项目、编写 REST 控制器到构建与部署 Kubernetes 原生镜像的全过程,让你快速上手 Quarkus,体验高效开发与部署的乐趣。
8 0
|
1天前
|
Java 开发者
Java中的异常处理机制:理解与应用
在Java编程中,异常处理是确保程序稳定性和可靠性的关键。本文将深入探讨Java的异常处理机制,包括异常的分类、捕获和处理方法,以及如何有效地使用这些工具来提高代码质量。
|
3天前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的应用与实践
在软件开发中,设计模式是解决问题的最佳实践。本文将探讨PHP中的策略模式,通过实际应用案例,展示如何有效地使用策略模式来提高代码的灵活性和可维护性。我们将从基本概念入手,逐步深入到实际编码,最终实现一个具有策略模式的应用。
|
设计模式 算法 安全
Java中23种面试常考的设计模式之策略模式(Strategy)---行为型模式
Java中23种面试常考的设计模式之策略模式(Strategy)---行为型模式
82 1