策略模式

简单来说就是告别代码中冗长的if/else,使不同的也不走不同的业务策略类,例如:电商支付场景等,有微信、支付宝、银联卡支付等等,不同的支付需要调用不同的SDK
恰巧最近在做组织机构结构改造的业务,考虑到后续业务可能多变,所以写代码时使用的策略模式。
接下来上代码:

  1. 书写基类接口,具体实现类均实现该接口(OrganResultDataStrategy)
  2. 组织机构策略类获取工厂(OrganSyncStructureFactory)
  3. 其他细节,编写传输上下文(OrganContextDTO)
  4. 也可以编写一个公共方法的父类,这样通用的功能直接super调用父类方法即可

下面的方法名自己可以灵活修改,主要是实现的方式

OrganResultDataStrategy接口

/**
 * 组织机构结构改造处理基类 <br>
 * 其他各种策略实现该接口
 * <p>
 * Date-Time: 2021/08/05 11:17
 * </p>
 * @Author fyan
 * @Version 3.2.6
 **/
public interface OrganResultDataStrategy {

    /**
     * 根据配置获取制定的结构
     * 需要的参数 boolean start 是否进行组织机构结构修改, int level 修改到哪个层级之下, String strategy 具体的处理策略类名称
     * @param strategy Organ config JSON 文件对象
     * @return
     */
    boolean transformType(JSONObject strategy);

    /**
     * 数据封装方法
     * @param organContextDTO 组织机构数据传输上下文
     * @return
     */
    Object capsulation(final OrganContextDTO organContextDTO);

}

transformType方法是判断最终获取哪个实现类的方法,capsulation方法是具体的实现方法

OrganContextDTO上下文

/**
 * @description: 组织机构结构修改数据传输上下文 .<br>
 * <p>
 * @DateTime: 2021-08-05 14:28
 * </p>
 * @Author fyan
 * @Version
 **/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class OrganContextDTO {
    // 最终导出的数据
    ExportOrgan exportOrgan;
    // 组织机构原始数据,用于获取根节点或者父节点信息等
    List<IBaseOrgan> organList;
}

参数封装你们业务所需要的实体类即可

OrganSyncStructureFactory接口

/**
 * 组织机构处理策略工厂类. <br>
 * 根据制定的策略获取制定的处理方式
 * <p>
 * Date-Time: 2021/08/05 11:15
 * </p>
 * @Author fyan
 * @Version 3.2.6
 **/
public final class OrganSyncStructureFactory {

    private OrganSyncStructureFactory(){
        throw new IllegalStateException("Utility class");
    }

    public static OrganResultDataStrategy getResultData(JSONObject strategy){
        Map<String, OrganResultDataStrategy> beansOfType = SpringUtils.getBeansOfType(OrganResultDataStrategy.class);
        for (Map.Entry<String, OrganResultDataStrategy> entry : beansOfType.entrySet()) {
            OrganResultDataStrategy value = entry.getValue();
            if (value.transformType(strategy)){
                return value;
            }
        }
        return null;
    }


}

需要搭配Spring的上下文来实现具体实现类的获取
可以编写成工具类,也可以直接使用Spring上下文进行操作

public final class SpringUtils {
    private SpringUtils(){}

    private static ApplicationContext applicationContext;
    public static void setApplicationContext(ApplicationContext context){
        applicationContext = context;
    }

    public static <T> T getBean(Class<T> requiredType){
        return applicationContext.getBean(requiredType);
    }

    public static <T> T getBean(String beanName, Class<T> beanType){
        return applicationContext.getBean(beanName,beanType);
    }

    public static Object getBean(String beanName){
        return applicationContext.getBean(beanName);
    }

    public String get(String key) {
        return getBean(Environment.class).getProperty(key);
    }

    public static <T> Collection<T> getBeans(Class<T> type) {
        Map<String, T> beans = applicationContext.getBeansOfType(type);
        return beans.values();
    }
    public static <T> Map<String, T> getBeansOfType(Class<T> baseType) {
        return applicationContext.getBeansOfType(baseType);
    }
}

main方法下添加代码:

public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(YdxcXcywApplication.class, args);
        // 添加下面这段
        SpringUtils.setApplicationContext(context);
    }

OrganDataDeal类

最终实现类均继承该类,用于实现公共的功能。

/**
 * @description: 涉及公共的数据处理类 .<br>
 * <p>
 * @DateTime: 2021-08-05 13:55
 * </p>
 * @Author fengyan
 * @Version 3.2.6
 **/
@Component
@Slf4j
public class OrganDataDeal {

    @Autowired
    private IOrganService organService;

    /**
     * 父类管理处理方法,用于处理获取所有省级下,所有的子单位、部门
     * @return
     */
    Map<String,String> getSuperStructureMap(){

        return null;
    }
}

实现类(NormalOrganResultDataStrategy、SuperCChangeOrganResultDataStrategy)

接下来是实现的具体策略类

/**
 * 正常的组织机构数据结构,不需要任何处理.<br>
 * <p>
 * Date-Time: 2021/08/05 13:43
 * </p>
 * @Author fyan
 * @Version 3.2.6
 **/
@Component
@Slf4j
public class NormalOrganResultDataStrategy extends OrganDataDeal implements OrganResultDataStrategy{
    public static final String STRATEGY = "normal";

    @Override
    public boolean transformType(JSONObject strategy) {
        JSONObject changeStructure = strategy.getJSONObject(OrganSyncFieldEnum.CHANGESTRUCTURE.getCode());
        String normal = Objects.toString(changeStructure.get(OrganSyncFieldEnum.STRATEGY.getCode()));
        return StringUtils.equalsAnyIgnoreCase(STRATEGY, normal);
    }

    @Override
    public Object capsulation(final OrganContextDTO organContextDTO) {
        // 不做任何处理
        return organContextDTO;
    }

}
/**
 * @description: 修改机构、部门、人员等部分父类ID信息 .<br>
 * <p>
 * @DateTime: 2021-08-05 13:50
 * </p>
 * @Author fengyan
 * @Version 3.2.6
 **/
@Component
@Slf4j
public class SuperCChangeOrganResultDataStrategy extends OrganDataDeal implements OrganResultDataStrategy{

    public static final String STRATEGY = "SuperStructureChange";
    public static JSONObject CONFIG;

    @Override
    public boolean transformType(JSONObject strategy) {
        CONFIG = strategy;
        JSONObject changeStructure = strategy.getJSONObject(OrganSyncFieldEnum.CHANGESTRUCTURE.getCode());
        String superStructureChange = Objects.toString(changeStructure.get(OrganSyncFieldEnum.STRATEGY.getCode()));
        return StringUtils.equalsAnyIgnoreCase(STRATEGY, superStructureChange);
    }

    @Override
    public Object capsulation(final OrganContextDTO organContextDTO) {
        // 映射关系,重新处理后的父类与子类关系
        Map<String, String> superStructureMap = super.getSuperStructureMap();
        // 导出的数据
        // 处理单位
        // 处理部门
        // 清理资源
        return organContextDTO;
    }

}

调用

// 处理导出的组织机构
		JSONObject strategy = organSyncConfigCache.get();
		OrganResultDataStrategy resultData = OrganSyncStructureFactory.getResultData(strategy);
		OrganContextDTO organContextDTO = OrganContextDTO
				.builder()
				.exportOrgan(exportOrgan)
				.organList(organList)
				.build();
		resultData.capsulation(organContextDTO);

总结

主要就是策略的选择,只需要制定规则,就可以通过具体的标识选择指定的策略,并且每次修改也不用担心影响其他的功能。

方法中的参数都是可以根据自己的业务作出的修改,我这里使用JSONObject是因为业务需求用它比较方便,最好使用POJO类或者String,方便别人看你的代码。

有问题留言,看到会回复。