✨重磅!盹猫的个人小站正式上线啦~诚邀各位技术大佬前来探秘!✨
这里有:
- 硬核技术干货:编程技巧、开发经验、踩坑指南,带你解锁技术新姿势!
- 趣味开发日常:代码背后的脑洞故事、工具测评,让技术圈不再枯燥~
- 独家资源分享:开源项目、学习资料包,助你打怪升级快人一步!
👉 点击直达→ 盹猫猫的个人小站 👈
🌟 来逛逛吧,说不定能挖到你正在找的技术宝藏哦~
目录
欢迎来到 盹猫(>^ω^<)的博客
本篇文章主要介绍了
[SpringBoot中策略模式使用]
❤博主广交技术好友,喜欢文章的可以关注一下❤
简介
在日常开发中,总会遇到这种情况,需要根据数据类型,选择不同的服务进行执行,或者根据类型查询数据库不同表的数据. 有的人可能立刻想到了使用If else分支或者Switch进行类型的判断,然后调用不同的服务进行处理. 在一些简单应用中,其实是可以,但当分支较多时,这么设计就会使代码臃肿,并且处理速度会非常的慢. 这时候就可以考虑使用策略模式来进行代码的重构.
策略结构
策略模式主要就是为解决多分支的选择,如上图所示,策略结构中核心为策略工厂,工厂中一般会维护着一个或多个Map(可以将这个工厂与switch分支或IF语句对等),Map中维护着多个策略,就是多个不同类型的处理服务实现(可以理解为分支内的具体逻辑).这样就保证了,在主服务(这里是PointDataService)可以直接使用工厂类通过类型,选择具体的处理策略进行处理.
代码案例
在这个案例中,需要实现(防火点,水源点)类型的查询,因为都是点位数据(但又有不同的数据字段),所以用一个点位数据服务进行查询实现.
定义类型枚举
package com.uav.kunyv.entity;
/**
* 该枚举类用于定义点位数据类型。
*/
public enum PointDataTypeEnum {
/**
* 防火点类数据
*/
FIRE("Fire"),
/**
* 取水点类数据
*/
RESERVE("Reserve"),
/**
* 监控点类数据
*/
CAMERA("Camera"),
/**
* 其他类型点位数据
*/
OTHER("Other");
String value;
PointDataTypeEnum(String value) {
this.value = value;
}
public String value() {
return this.value;
}
public static PointDataTypeEnum fromValue(String value) {
for (PointDataTypeEnum type : values()) {
if (type.value.equals(value)) {
return type;
}
}
return OTHER; // 或抛出异常
}
}
创建实体类
基础数据(抽象类)
package com.uav.kunyv.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @author xh
* 2025/7/31 10:17
*/
@Data
public abstract class BaseEntity implements Serializable {
/**
* id
*/
@TableId
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
private Long creator;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createDate;
}
点位数据(抽象类)
package com.uav.kunyv.entity;
import lombok.Data;
/**
* 所有点位类型数据的抽象类
* 防火点、水库、摄像头等都可以继承此类
* 继承后 id,lon,lat,dictId,dataType可不用重写
*/
@Data
public abstract class BasePointDataEntity extends BaseEntity{
/**
* 经度
*/
private Double lon;
/**
* 纬度
*/
private Double lat;
/**
* 类型ID
*/
private Long dictId;
/**
* 数据类型ID
*/
private PointDataTypeEnum dataType;
}
防火点(实体类)
package com.uav.kunyv.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
/**
* create by 2023/12/18
*
* @author Mr.Cat
* @since 1.0
**/
@Data
@TableName("tb_fire_data")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class FireDataEntity extends BasePointDataEntity implements IPointData{
/** 名称 */
private String name;
/** 负责人 */
private String charge;
/** 人员列表 */
private Long personnel;
/** 负责人联系方式 */
private String chargePhone;
/** 设备 */
private String device;
/** 责任人 */
private String duty;
/** 车辆 */
private String vehicle;
@Override
public PointDataTypeEnum getPointType() {
return PointDataTypeEnum.FIRE;
}
}
水源点(实体类)
package com.uav.kunyv.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
/**
* create by 2024/1/16
* 水源地实体类
* @author Mr.Cat
* @since 1.0
**/
@Data
@TableName("tb_reservoir")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Reservoir extends BasePointDataEntity implements IPointData {
/** 类型 */
private String type;
/** 村庄名 */
private String village;
/** 容量 */
private String capacity;
/** 深度 */
private String depth;
/** 平均深度 */
private String avgDepth;
/** 面积 */
private String area;
@Override
public PointDataTypeEnum getPointType() {
return PointDataTypeEnum.RESERVE;
}
}
创建服务
点位服务(接口)
package com.uav.kunyv.service;
import com.uav.kunyv.common.page.PageData;
import com.uav.kunyv.entity.IPointData;
import java.util.Map;
public interface PointDataService {
//分页查询点位数据
PageData<IPointData> page(Map<String,Object> params);
void add(IPointData pointData);
}
点位服务(实现类)
package com.uav.kunyv.service.impl;
import com.uav.kunyv.common.page.PageData;
import com.uav.kunyv.common.service.impl.BaseService;
import com.uav.kunyv.dao.PointDataDao;
import com.uav.kunyv.entity.*;
import com.uav.kunyv.service.PointDataService;
import com.uav.kunyv.service.strategy.PointDataStrategyFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
@Slf4j
public class PointDataServiceImpl implements PointDataService {
@Autowired
PointDataStrategyFactory pointDataStrategyFactory;
@Override
public PageData<IPointData> page(Map<String, Object> params) {
PointDataTypeEnum pointType = PointDataTypeEnum.fromValue((String) params.get("pointType"));
return pointDataStrategyFactory.getStrategy(pointType).page(params);
}
@Override
public void add(IPointData pointData) {
pointDataStrategyFactory.getStrategy(pointData.getPointType()).add(pointData);
}
}
创建策略
策略工厂
package com.uav.kunyv.service.strategy;
import com.uav.kunyv.entity.PointDataTypeEnum;
import com.uav.kunyv.exception.SysException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.EnumMap;
import java.util.Map;
@Service
public class PointDataStrategyFactory {
private final Map<PointDataTypeEnum, PointDataStrategy> strategyMap = new EnumMap<>(PointDataTypeEnum.class);
@Autowired
public PointDataStrategyFactory(
FireDataPointStrategy fireDataPointStrategy) {
strategyMap.put(PointDataTypeEnum.FIRE, fireDataPointStrategy);
}
public PointDataStrategy getStrategy(PointDataTypeEnum type) {
PointDataStrategy strategy = strategyMap.get(type);
if (strategy == null) {
throw new SysException("不支持的点位类型: " + type);
}
return strategy;
}
}
策略服务(接口)
package com.uav.kunyv.service.strategy;
import com.uav.kunyv.common.page.PageData;
import com.uav.kunyv.entity.IPointData;
import java.util.Map;
public interface PointDataStrategy {
PageData <IPointData> page(Map<String, Object> params);
void add(IPointData pointData);
void del(Long[] ids);
void update(IPointData pointData);
}
防火点策略服务(实现)
package com.uav.kunyv.service.strategy;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.uav.kunyv.common.constant.Constant;
import com.uav.kunyv.common.page.PageData;
import com.uav.kunyv.common.service.impl.BaseService;
import com.uav.kunyv.common.util.ConvertUtils;
import com.uav.kunyv.dao.FireDataDao;
import com.uav.kunyv.entity.FireDataEntity;
import com.uav.kunyv.entity.IPointData;
import com.uav.kunyv.exception.SysException;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Service
public class FireDataPointStrategy extends BaseService<FireDataDao,FireDataEntity> implements PointDataStrategy{
@Override
public PageData<IPointData> page(Map<String, Object> params) {
String[] orderFields = {Constant.CREATE_DATE};
boolean[] asc = {false};
IPage<FireDataEntity> page = getPage(params, orderFields, asc);
List<FireDataEntity> list = baseDao.list(params);
return new PageData<>(new ArrayList<>(list),page.getTotal());
}
@Override
public void add(IPointData pointData) {
if (pointData == null){
throw new SysException("pointData is null");
}
FireDataEntity entity = ConvertUtils.sourceToTarget(pointData, FireDataEntity.class);
insert(entity);
}
@Override
public void del(Long[] ids) {
deleteBatchIds(Arrays.asList(ids));
}
@Override
public void update(IPointData pointData) {
if (pointData == null){
throw new SysException("pointData is null");
}
FireDataEntity entity = ConvertUtils.sourceToTarget(pointData, FireDataEntity.class);
updateById(entity);
}
}
在上述代码中,核心代码为策略工厂的实现,通过创建策略工厂和实现相关策略,可以保证在点位服务的实现类中可以通过工厂类进行不同策略的调用.从而减少了传统的判断分支方法的实现,同时整个系统的可扩展性和运行速度得到了优化.
速度优化主要原因是通过Map选择比传递的分支判读速度更快.
如果你对区块链内容感兴趣可以查看我的专栏:小试牛刀-区块链
感谢您的关注和收藏!!!!!!