策略模式-使用枚举newInstance
- 前言
- 一、枚举类:MarkCheckDataTypeEnum
- 二、抽象类:AbstractMarkChecker
- 三、检查类:MarkPeopleChecker
- 四、demo演示
- 总结
前言
很久没写文章了~~
吐槽下:入职新公司后,基本在搬砖,我爱劳动我光荣~
遇到一个小需求:根据接口入参-不同类型,进行不同字段的检查。不想写if…else嵌套,就写了个最简单的策略模式。
一、枚举类:MarkCheckDataTypeEnum
创建一个枚举类,将业务实现类作为枚举的一个属性,
如:
STD_PEOPLE(“std_people”, MarkPeopleChecker.class)
public enum MarkCheckDataTypeEnum {/*** 主体-人*/STD_PEOPLE("std_people", MarkPeopleChecker.class),/*** 主体-房屋*/STD_HOUSE("std_house", MarkHouseChecker.class),/*** 主体-小区*/STD_RESIDENTIAL("std_residential", MarkResidentialChecker.class),/*** 主体-商铺*/STD_BUSINESS("std_business", MarkBusinessChecker.class),/*** 主体-企业*/STD_ENTERPRISE("std_enterprise", MarkEnterpriseChecker.class),/*** 主体-区域*/STD_PARK("std_park", MarkParkChecker.class),;/*** 主体类型*/private String dataType;/*** 主体的预检查类*/private Class<?> checker;MarkCheckDataTypeEnum(String dataType, Class checker) {this.dataType = dataType;this.checker = checker;}public String getDataType() {return dataType;}public void setDataType(String dataType) {this.dataType = dataType;}public Class<?> getChecker() {return checker;}public void setChecker(Class<?> checker) {this.checker = checker;}/*** 根据主体获取检查类** @param dataType 主体类型* @return 检查类* @throws Exception new实例异常*/public static AbstractMarkChecker getMarkChecker(String dataType) throws Exception {for (MarkCheckDataTypeEnum markCheckDataTypeEnum : MarkCheckDataTypeEnum.values()) {if (markCheckDataTypeEnum.getDataType().equals(dataType)) {return (AbstractMarkChecker) markCheckDataTypeEnum.getChecker().newInstance();}}return MarkCommonChecker.class.newInstance();}
}
二、抽象类:AbstractMarkChecker
BusinessException这个是自定义异常,用于抛出检查类:检查不通过的原因。
1:有点编码基础的,也可以换成自己的异常类
2:或者把不通过的原因返回出来,如:
public abstract String check(List<String> assetFieldNameList);
我的代码如下:
import lobster.base.exception.BusinessException;
import org.springframework.stereotype.Service;import java.util.List;/*** 保存标注时,进行必要信息检查* 人:* 未检测到【证件号】或者【姓名】+【手机号】标注字段,而有其他人员非必要信息字段标注的情况下* 提示:您的标注信息未包含人员必要信息字段【证件号】或【姓名+手机号】,可能导致人员信息数据无法入库,请仔细检查。* <p>* 房屋:* 未检测到【房屋地址】或者【楼栋+单元+楼层+房号】或者【房号】标注字段,而有其他房屋非必要信息字段标注的情况下* 提示:您的标注信息未包含房屋必要信息字段【房屋地址】或【楼栋+单元+楼层+房号】或【房号】,可能导致房屋信息数据无法入库,请仔细检查。* <p>* <p>* 小区:* 未检测到【小区名】标注字段,而有其他小区非必要信息字段标注的情况下* 提示:您的标注信息未包含小区必要信息字段【小区名】,可能导致小区信息数据无法入库,请仔细检查。* <p>* 商铺:* 未检测到【商铺名称+商铺地址】标注字段,而有其他商铺非必要信息字段标注的情况下* 提示:您的标注信息未包含商铺必要信息字段【商铺名称+商铺地址】,可能导致商铺信息数据无法入库,请仔细检查。* <p>* 企业:* 未检测到【企业名称+企业地址】标注字段,而有其他企业非必要信息字段标注的情况下* 提示:您的标注信息未包含企业必要信息字段【企业名称+企业地址】,可能导致企业信息数据无法入库,请仔细检查。* <p>* 区域:* 未检测到【区域名称】标注字段,而有其他区域非必要信息字段标注的情况下* 提示:您的标注信息未包含区域必要信息字段【区域名称】,可能导致区域信息数据无法入库,请仔细检查。** @author lobster*/
@Service
public abstract class AbstractMarkChecker {/*** 检查主体必要字段** @param assetFieldNameList 当前主体,标注时选择的字段* @throws BusinessException 业务异常*/public abstract void check(List<String> assetFieldNameList) throws BusinessException;
}
三、检查类:MarkPeopleChecker
检查类和MarkCheckDataTypeEnum的checker对应。
这里只贴一个MarkPeopleChecker,检查类都差不多
import lobster.base.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import java.util.List;/*** 人:* 未检测到【证件号】或者【姓名】+【手机号】标注字段,而有其他人员非必要信息字段标注的情况下* 提示:您的标注信息未包含人员必要信息字段【证件号】或【姓名+手机号】,可能导致人员信息数据无法入库,请仔细检查。** @author lobster*/
@Slf4j
@Service
public class MarkPeopleChecker extends AbstractMarkChecker {private static final String NAME = "name";private static final String ID_CARD = "id_card";private static final String MOBILE = "mobile";@Overridepublic void check(List<String> assetFieldNameList) throws BusinessException {boolean containsName = assetFieldNameList.contains(NAME);boolean containsIdCard = assetFieldNameList.contains(ID_CARD);boolean containsMobile = assetFieldNameList.contains(MOBILE);if (containsIdCard) {log.info("标注主体:std_people 存在【证件号】");return;}if (containsName && containsMobile) {log.info("标注主体:std_people 存在【姓名】+【手机号】");return;}throw new BusinessException(500, "您的标注信息未包含人员必要信息字段【证件号】或【姓名+手机号】,可能导致人员信息数据无法入库,请仔细检查");}
}
四、demo演示
直接执行main方法就行
代码如下(示例):
import com.example.springDemo.markprecheck.MarkCheckDataTypeEnum;
import com.google.common.collect.Lists;
import lobster.base.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@Slf4j
@RestController("mark/pre/check")
public class MarkPreCheckController {@GetMapping(value = "demo", name = "通过枚举实现策略")public static String demo() {try {MarkCheckDataTypeEnum.getMarkChecker("std_people").check(Lists.newArrayList("name", "sex"));} catch (BusinessException e) {log.error("出现业务异常:", e);return e.getMsg();} catch (Exception e) {log.error("出现系统异常:", e);return e.getMessage();}return "success";}//直接执行main方法就行public static void main(String[] args) {String errorMsg = demo();System.out.println(errorMsg);}
}
实例代码打印结果:
总结
总来的来,emm~~这个示例很简单,没啥说的。
主要是通过MarkCheckDataTypeEnum.getMarkChecker()来获取检查类实例,然后调用检查类的check方法。
通过扩展枚举类MarkCheckDataTypeEnum与具体的检查类,对代码进行解耦。但解耦不多,不如工厂+策略的方式。