国家工商登记网,网站排名优化专业定制,网站编程学习,布谷海南网站建设文章目录 前言一、策略模式是什么#xff1f;二、策略模式应用场景三、策略模式优点四、策略模式缺点五、场景案例#xff1a;类型统计1.项目结构2.UML图解3.代码实现3.1 指标枚举3.2 请求体3.3 响应体3.4.分析统计指标策略3.5.接口3.6.扩展接口3.7.接口实现3.8.控制层 六、P… 文章目录 前言一、策略模式是什么二、策略模式应用场景三、策略模式优点四、策略模式缺点五、场景案例类型统计1.项目结构2.UML图解3.代码实现3.1 指标枚举3.2 请求体3.3 响应体3.4.分析统计指标策略3.5.接口3.6.扩展接口3.7.接口实现3.8.控制层 六、PostMan测试1.测试getListData()接口2.测试getChartData()接口3.getObtainInventory()扩展接口 总结 前言
在做统计的业务开发中常常伴随着用户选择不同类型的统计而动态的加载数据返回的数据也会动态的改变比如说一张商超里面可能有贩卖肉蛋禽、蔬菜、饮料、水果等我们需要根据这几种类型指标算法不同去生成各自的统计数据如果根据不同的类型写不同的接口可以实简单现该功能但带来的问题是接口定义太多重复方法定义过多如果统一一个接口、内容使用if去走分支也可以实现相同的效果但还是不够理想化理想的是不需要手动的添加if分支而是做到自动匹配到对应算法执行指定的流程那么这时候就需要策略模式来帮我们实现这一步操作了 一、策略模式是什么
策略模式是一种行为型设计模式它定义了一系列算法或策略并将它们封装起来使它们可以互相替换。在使用策略模式时可以通过改变不同的算法或策略来改变对象的行为。策略模式通常包含两部分策略接口和策略实现类。策略接口定义了对某种行为的抽象而策略实现类则提供了具体的算法或策略实现。
二、策略模式应用场景
针对同一类型问题的多种处理方式仅仅是具体行为有差别时。需要动态选择算法和策略时。当一个对象需要通过多种行为方式中的一种进行某种操作时。在不希望客户端知道具体实现细节的情况下可采用策略模式对外提供接口。多个类只有在算法或行为上稍有不同的场景。假设有一个系统需要根据用户的不同操作系统显示不同的界面风格。可以使用策略模式将不同操作系统的界面风格作为不同的策略实现类并通过定义一个策略接口来对外暴露相应的方法。策略模式还可以用于设计游戏中的战斗系统根据不同角色的属性和职业特点选取最优的战斗策略进行战斗。 总之策略模式适用于多个类只有在算法或行为上稍有不同的场景并且在运行时需要动态地选择不同的算法或策略的情况下。 三、策略模式优点
策略模式可以让算法或策略独立于使用它们的客户端而变化从而实现代码复用。策略模式可以让算法或策略在不影响代码结构的情况下灵活地变化降低了代码维护的成本。策略模式可以避免使用大量的 if-else 语句或者 switch 语句来进行分支处理增强了代码的可读性和可维护性。策略模式可以在运行时动态地改变算法或策略因此可以根据需要进行适当的选择和组合。 四、策略模式缺点
策略模式会增加系统需要的类的数量可能会导致代码变得更加复杂和难以理解。策略模式需要客户端了解不同的策略之间的差异增加了客户端的编码难度。策略模式可能会导致不必要的运行时开销因为需要动态地选择和组合算法或策略。 五、场景案例类型统计
1.项目结构 2.UML图解 3.代码实现
3.1 指标枚举
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Getter;Getter
AllArgsConstructor
JsonFormat(shape JsonFormat.Shape.OBJECT)
public enum StatisticalIndicatorsEnum {/*** 肉*/MEAT(1, 肉, meatAnalysisTableService),/*** 水果*/FRUIT(2, 水果, fruitAnalysisTableService),/*** 蔬菜*/VEGETABLE(3, 蔬菜, vegetableAnalysisTableService),/*** 饮料*/BEVERAGE(4, 饮料, beverageAnalysisTableService);/*** 编码*/private final Integer code;/*** 注释*/private final String desc;/*** 对应策略*/private final String strategyName;
}3.2 请求体
import com.fasterxml.jackson.annotation.JsonFormat;
import com.mxf.code.strategy_factory.enums.StatisticalIndicatorsEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.web.bind.annotation.ModelAttribute;import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;/*** 统计图Request*/
Data
ApiModel(value 统计图Request)
public class StatisticsRequest implements Serializable {private static final long serialVersionUID 1L;NotBlank(message 统计指标不能为空)ApiModelProperty(value 统计指标)private StatisticalIndicatorsEnum statisticalIndicatorsEnum;NotNull(message 统计起始时间不能为空)ApiModelProperty(value 开始时间格式yyyy-MM-dd)JsonFormat(pattern yyyy-MM-dd)private Date startDate;NotNull(message 统计截止时间不能为空)ApiModelProperty(value 结束时间格式yyyy-MM-dd)JsonFormat(pattern yyyy-MM-dd)private Date endDate;ModelAttribute(statisticalIndicators)public void setStatisticalIndicatorsEnum(StatisticalIndicatorsEnum statisticalIndicatorsEnum) {this.statisticalIndicatorsEnum statisticalIndicatorsEnum;}
}3.3 响应体
import lombok.Data;/*** author mxf* version 1.0* description: 响应体Base* date 2023/5/26*/
Data
public abstract class BaseResponse {
}import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;import java.io.Serializable;
import java.math.BigDecimal;/*** author 28382*/
Data
ApiModel(value 蔬菜)
EqualsAndHashCode(callSuper true)
public class BeverageAvailabilityListResponse extends BaseResponse implements Serializable {private static final long serialVersionUID 1L;ApiModelProperty(value 统计时间)private String xDate;ApiModelProperty(value 饮料类型名称)private String beverageTypeName;ApiModelProperty(value 销售件数)private Double salesQuantity;ApiModelProperty(value 销售金额)private BigDecimal salesAmount;
}import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;import java.io.Serializable;
import java.math.BigDecimal;/*** author 28382*/
Data
ApiModel(value 水果图表响应体)
EqualsAndHashCode(callSuper true)
public class FruitAvailabilityChartResponse extends BaseResponse implements Serializable {private static final long serialVersionUID 1L;ApiModelProperty(value 统计时间)private String xDate;ApiModelProperty(value 本年销售总额)private BigDecimal currentYearSalesAmount;ApiModelProperty(value 去年销售金额)private BigDecimal previousYearSalesAmount;
}import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;import java.io.Serializable;
import java.math.BigDecimal;/*** author 28382*/
Data
ApiModel(value 水果)
EqualsAndHashCode(callSuper true)
public class FruitAvailabilityListResponse extends BaseResponse implements Serializable {private static final long serialVersionUID 1L;ApiModelProperty(value 统计时间)private String xDate;ApiModelProperty(value 肉类名)private String fruitTypeName;ApiModelProperty(value 销售量kg)private Double salesVolume;ApiModelProperty(value 销售金额)private BigDecimal salesAmount;
}import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;import java.io.Serializable;
import java.math.BigDecimal;/*** author 28382*/
Data
ApiModel(value 肉)
EqualsAndHashCode(callSuper true)
public class MeatAvailabilityListResponse extends BaseResponse implements Serializable {private static final long serialVersionUID 1L;ApiModelProperty(value 统计时间)private String xDate;ApiModelProperty(value 肉类名)private String meatTypeName;ApiModelProperty(value 销售量kg)private Double salesVolume;ApiModelProperty(value 销售金额)private BigDecimal salesAmount;
}import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;import java.io.Serializable;
import java.math.BigDecimal;/*** author 28382*/
Data
ApiModel(value 蔬菜)
EqualsAndHashCode(callSuper true)
public class VegetableAvailabilityListResponse extends BaseResponse implements Serializable {private static final long serialVersionUID 1L;ApiModelProperty(value 统计时间)private String xDate;ApiModelProperty(value 肉类名)private String vegetableName;ApiModelProperty(value 销售量kg)private Double salesVolume;ApiModelProperty(value 销售金额)private BigDecimal salesAmount;
}3.4.分析统计指标策略
管理策略bean
import com.mxf.code.strategy_factory.enums.StatisticalIndicatorsEnum;
import org.springframework.stereotype.Service;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** 分析统计指标策略** author 28382*/
Service
public class AnalysisTableStrategyContext {private final MapString, AnalysisTableService analysisTableMap new ConcurrentHashMap();public AnalysisTableStrategyContext(MapString, AnalysisTableService strategyMap) {this.analysisTableMap.putAll(strategyMap);}/*** param statisticalIndicatorsEnum 指标枚举* return com.mxf.code.strategy_factory.service.AnalysisTableService* author mxf* description 获取实际统计策略* createTime 2023/5/26 14:08* paramType [com.mxf.code.strategy_factory.enums.StatisticalIndicatorsEnum]*/public AnalysisTableService getResource(StatisticalIndicatorsEnum statisticalIndicatorsEnum) {return analysisTableMap.get(statisticalIndicatorsEnum.getStrategyName());}
}3.5.接口
import com.mxf.code.strategy_factory.request.StatisticsRequest;
import com.mxf.code.strategy_factory.response.BaseResponse;import java.util.List;/*** 统计分析*/
public interface AnalysisTableService {/*** 获取统计图数据** param requestParams 入参* return*/ListBaseResponse getChartData(StatisticsRequest statisticsRequest);/*** 获取列表数据** param requestParams 入参* return*/ListBaseResponse getListData(StatisticsRequest statisticsRequest);
}3.6.扩展接口
import com.mxf.code.strategy_factory.request.StatisticsRequest;/*** author mxf* version 1.0* description: 水果(自定义接口)* date 2023/5/26*/
public interface FruitAnalysisTableService {/*** 获取水果库存** param statisticsRequest 入参* return*/Double getObtainInventory(StatisticsRequest statisticsRequest);
}3.7.接口实现
import com.mxf.code.strategy_factory.request.StatisticsRequest;
import com.mxf.code.strategy_factory.response.BaseResponse;
import com.mxf.code.strategy_factory.response.BeverageAvailabilityListResponse;
import com.mxf.code.strategy_factory.service.AnalysisTableService;
import org.springframework.stereotype.Service;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;/*** author mxf* version 1.0* description: 饮料* date 2023/5/26*/
Service(beverageAnalysisTableService)
public class BeverageAnalysisTableServiceImpl implements AnalysisTableService {Overridepublic ListBaseResponse getChartData(StatisticsRequest requestParams) {return null;}Overridepublic ListBaseResponse getListData(StatisticsRequest statisticsRequest) {ListBeverageAvailabilityListResponse resultList new ArrayList();BeverageAvailabilityListResponse beverageAvailabilityListResponse new BeverageAvailabilityListResponse();beverageAvailabilityListResponse.setXDate();beverageAvailabilityListResponse.setBeverageTypeName();beverageAvailabilityListResponse.setSalesQuantity(0.0D);beverageAvailabilityListResponse.setSalesAmount(new BigDecimal(0));resultList.add(beverageAvailabilityListResponse);return new ArrayList(resultList);}
}import com.mxf.code.strategy_factory.request.StatisticsRequest;
import com.mxf.code.strategy_factory.response.BaseResponse;
import com.mxf.code.strategy_factory.response.FruitAvailabilityChartResponse;
import com.mxf.code.strategy_factory.response.FruitAvailabilityListResponse;
import com.mxf.code.strategy_factory.service.AnalysisTableService;
import com.mxf.code.strategy_factory.service.FruitAnalysisTableService;
import org.springframework.stereotype.Service;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;/*** author mxf* version 1.0* description: 水果* date 2023/5/26*/
Service(fruitAnalysisTableService)
public class FruitAnalysisTableServiceImpl implements AnalysisTableService, FruitAnalysisTableService {Overridepublic ListBaseResponse getChartData(StatisticsRequest requestParams) {ListFruitAvailabilityChartResponse resultList new ArrayList();FruitAvailabilityChartResponse fruitAvailabilityChartResponse new FruitAvailabilityChartResponse();fruitAvailabilityChartResponse.setXDate(2022-05-25);fruitAvailabilityChartResponse.setCurrentYearSalesAmount(new BigDecimal(4));fruitAvailabilityChartResponse.setPreviousYearSalesAmount(new BigDecimal(5));FruitAvailabilityChartResponse fruitAvailabilityChartResponse2 new FruitAvailabilityChartResponse();fruitAvailabilityChartResponse2.setXDate(2022-05-26);fruitAvailabilityChartResponse2.setCurrentYearSalesAmount(new BigDecimal(1));fruitAvailabilityChartResponse2.setPreviousYearSalesAmount(new BigDecimal(2));resultList.add(fruitAvailabilityChartResponse);resultList.add(fruitAvailabilityChartResponse2);return new ArrayList(resultList);}Overridepublic ListBaseResponse getListData(StatisticsRequest statisticsRequest) {ListFruitAvailabilityListResponse resultList new ArrayList();FruitAvailabilityListResponse fruitAvailabilityListResponse new FruitAvailabilityListResponse();fruitAvailabilityListResponse.setXDate();fruitAvailabilityListResponse.setFruitTypeName();fruitAvailabilityListResponse.setSalesVolume(0.0D);fruitAvailabilityListResponse.setSalesAmount(new BigDecimal(0));resultList.add(fruitAvailabilityListResponse);return new ArrayList(resultList);}Overridepublic Double getObtainInventory(StatisticsRequest statisticsRequest) {return 334423423.44;}
}import com.mxf.code.strategy_factory.request.StatisticsRequest;
import com.mxf.code.strategy_factory.response.BaseResponse;
import com.mxf.code.strategy_factory.response.MeatAvailabilityListResponse;
import com.mxf.code.strategy_factory.service.AnalysisTableService;
import org.springframework.stereotype.Service;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;/*** author mxf* version 1.0* description: 肉* date 2023/5/26*/
Service(meatAnalysisTableService)
public class MeatAnalysisTableServiceImpl implements AnalysisTableService {Overridepublic ListBaseResponse getChartData(StatisticsRequest requestParams) {return null;}Overridepublic ListBaseResponse getListData(StatisticsRequest statisticsRequest) {ListMeatAvailabilityListResponse resultList new ArrayList();MeatAvailabilityListResponse meatAvailabilityListResponse new MeatAvailabilityListResponse();meatAvailabilityListResponse.setXDate();meatAvailabilityListResponse.setMeatTypeName();meatAvailabilityListResponse.setSalesVolume(0.0D);meatAvailabilityListResponse.setSalesAmount(new BigDecimal(0));resultList.add(meatAvailabilityListResponse);return new ArrayList(resultList);}
}import com.mxf.code.strategy_factory.request.StatisticsRequest;
import com.mxf.code.strategy_factory.response.BaseResponse;
import com.mxf.code.strategy_factory.response.VegetableAvailabilityListResponse;
import com.mxf.code.strategy_factory.service.AnalysisTableService;
import org.springframework.stereotype.Service;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;/*** author mxf* version 1.0* description: 蔬菜* date 2023/5/26*/
Service(vegetableAnalysisTableService)
public class VegetableAnalysisTableServiceImpl implements AnalysisTableService {Overridepublic ListBaseResponse getChartData(StatisticsRequest requestParams) {return null;}Overridepublic ListBaseResponse getListData(StatisticsRequest statisticsRequest) {ListVegetableAvailabilityListResponse resultList new ArrayList();VegetableAvailabilityListResponse vegetableAvailabilityListResponse new VegetableAvailabilityListResponse();vegetableAvailabilityListResponse.setXDate();vegetableAvailabilityListResponse.setVegetableName();vegetableAvailabilityListResponse.setSalesVolume(0.0D);vegetableAvailabilityListResponse.setSalesAmount(new BigDecimal(0));resultList.add(vegetableAvailabilityListResponse);return new ArrayList(resultList);}
}3.8.控制层
import com.mxf.code.strategy_factory.request.StatisticsRequest;
import com.mxf.code.strategy_factory.response.BaseResponse;
import com.mxf.code.strategy_factory.service.AnalysisTableService;
import com.mxf.code.strategy_factory.service.AnalysisTableStrategyContext;
import com.mxf.code.strategy_factory.service.FruitAnalysisTableService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** author mxf* version 1.0* description: 统计分析* date 2023/5/26*/
RestController
RequestMapping(statistical/indicators)
public class StatisticalIndicatorsController {Autowiredprivate AnalysisTableStrategyContext analysisTableStrategyContext;Autowiredprivate FruitAnalysisTableService fruitAnalysisTableService;GetMapping(listData)public ListBaseResponse getListData(StatisticsRequest statisticsRequest) {AnalysisTableService resource analysisTableStrategyContext.getResource(statisticsRequest.getStatisticalIndicatorsEnum());Assert.notNull(resource, 未知策略);return resource.getListData(statisticsRequest);}GetMapping(chartData)public ListBaseResponse getchartData(StatisticsRequest statisticsRequest) {AnalysisTableService resource analysisTableStrategyContext.getResource(statisticsRequest.getStatisticalIndicatorsEnum());Assert.notNull(resource, 未知策略);return resource.getChartData(statisticsRequest);}GetMapping(getFruitObtainInventory)public Double getFruitObtainInventory(StatisticsRequest statisticsRequest) {return fruitAnalysisTableService.getObtainInventory(statisticsRequest);}
}六、PostMan测试
1.测试getListData()接口
GetMapping(listData)
public ListBaseResponse getListData(StatisticsRequest statisticsRequest) {AnalysisTableService resource analysisTableStrategyContext.getResource(statisticsRequest.getStatisticalIndicatorsEnum());Assert.notNull(resource, 未知策略);return resource.getListData(statisticsRequest);
}2.测试getChartData()接口
GetMapping(chartData)
public ListBaseResponse getchartData(StatisticsRequest statisticsRequest) {AnalysisTableService resource analysisTableStrategyContext.getResource(statisticsRequest.getStatisticalIndicatorsEnum());Assert.notNull(resource, 未知策略);return resource.getChartData(statisticsRequest);
}3.getObtainInventory()扩展接口
GetMapping(getFruitObtainInventory)public Double getFruitObtainInventory(StatisticsRequest statisticsRequest) {return fruitAnalysisTableService.getObtainInventory(statisticsRequest);}总结
上述案例实现策略模式同时针对入参、出参、接口扩展做了更好的兼容。