需求
在项目中遇到一个问题,就是需要根据不同参数来执行不同的算法来得到一个处理结果,来实现对不同项目需求的动态适配。
实现思路
1.策略模式+模版方法模式
这种方式的难点在于策略模式如何与spring相结合,完成策略判断条件在项目启动时加载到对应的类中,这里网上有很多材料可以借鉴,就不过多阐述,推荐使用@PostConstruct注解。
只是这种方式对于业务逻辑处理起来相当方便,如果换成算法而言,就显得很不灵活。对于算法而言,它只在乎输入和输出,并不依赖于任何框架,即插即用。
2.责任链模式+类反射+模板方式模式
目标
- 以工具类的形式来使用算法
- 能根据对应的输入参数,动态选择不同的算法
代码演示
1.maven的pom文件
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.10</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.32</version>
</dependency>
</dependencies>
2. 算法抽象类
package voteCalculate;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 描述 : .
*
* @author : admin
* @version : v1
* @date : 2021-11-20 16:19
*/
@Data
@EqualsAndHashCode
@Accessors(chain = true)
public abstract class VoteCalculateHandle {
/**
* 命中元素链.
*/
private ValidChain chain;
/**
* 投票人. notEmpty.
*/
private List<String> memberDtoList;
/**
* 投票记录集合. notEmpty.
*/
private List<String> voteRecordList;
/**
* 计算投票结论.
*
* @return .
*/
public VoteCalculateResultDto calculate() {
checkParameter();
return calculateItem();
}
/**
* 校验元素.
*/
protected abstract void checkParameter();
/**
* 计算投票结论.
*
* @return .
*/
protected abstract VoteCalculateResultDto calculateItem();
public void addValid(String key, Object value) {
if (chain == null){
chain = new ValidChain(key, value);
}else{
ValidChain tmp = chain;
while (tmp.getNext() != null) {
tmp = tmp.getNext();
}
tmp.setNext(new ValidChain(key, value));
}
}
}
@Data
@EqualsAndHashCode
@Accessors(chain = true)
class ValidChain {
private String key;
private Object value;
private ValidChain next;
public ValidChain(String key, Object value) {
this.key = key;
this.value = value;
}
}
3.算法实现子类
package voteCalculate;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 描述 : 实现算法类1.
*
* @author : admin
* @version : v1
* @date : 2021-11-20 16:59
*/
@Data
@EqualsAndHashCode
@Accessors(chain = true)
public class VoteCalculateOneHandle extends VoteCalculateHandle {
public VoteCalculateOneHandle() {
// 生成调用链
addValid("voteType", "0");
addValid("voteRound", 1);
}
@Override
protected void checkParameter() {
}
@Override
protected VoteCalculateResultDto calculateItem() {
VoteCalculateResultDto voteCalculateResultDto = new VoteCalculateResultDto();
voteCalculateResultDto.setVoteResultId("运行算法1");
return voteCalculateResultDto;
}
}
4.算法的入参类
package voteCalculate;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
/**
* 描述 : .
*
* @author : admin
* @version : v1
* @date : 2021-11-20 16:19
*/
@Data
@EqualsAndHashCode
@Accessors(chain = true)
public class VoteCalculateParameterDto implements Serializable {
/**
* 项目环境.
*/
private String environmentCode;
/**
* 投票类型. notEmpty.
*/
private String voteType;
/**
* 会议投票人. notEmpty.
*/
private List<String> memberDtoList;
/**
* 投票记录集合. notEmpty.
*/
private List<String> voteRecordList;
}
5.投票结论类
package voteCalculate;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 描述 : .
*
* @author : admin
* @version : v1
* @date : 2021-11-20 16:19
*/
@Data
@EqualsAndHashCode
@Accessors(chain = true)
public class VoteCalculateResultDto implements Serializable {
/**
* 投票结论id.
*/
private String voteResultId;
/**
* 投票结论中文.
*/
private String voteResultTxt;
/**
* 详细投票结论.
*/
private String voteResultItem;
}
6.算法工具类
package voteCalculate;
import com.alibaba.fastjson.JSONObject;
import org.reflections.Reflections;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* 描述 : .
*
* @author : admin
* @version : v1
* @date : 2021-11-20 16:44
*/
public class VoteCalculateUtil {
/**
* 计算投票结论
*
* @param parameterDto 入参.
* @return .
*/
public static VoteCalculateResultDto getVoteCalculateResult(VoteCalculateParameterDto parameterDto) throws Exception {
VoteCalculateHandle planDto = getPlanDto(parameterDto);
if (planDto == null) {
throw new Exception();
}
return planDto.calculate();
}
/**
* 获取方案对象,采用反射来命中处理类..
*
* @param parameterDto 入参校验.
* @return .
*/
private static VoteCalculateHandle getPlanDto(VoteCalculateParameterDto parameterDto) {
List<VoteCalculateHandle> handleList = getHandleList();
for (VoteCalculateHandle handle : handleList) {
ValidChain chain = handle.getChain();
while (chain != null) {
String key = chain.getKey();
Object value = chain.getValue();
boolean validFlag = false;
try {
Field keyField = parameterDto.getClass().getDeclaredField(key);
if (keyField != null) {
// 允许访问
keyField.setAccessible(true);
Object keyValue = keyField.get(parameterDto);
if (value.equals(keyValue)) {
validFlag = true;
}
}
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
if (!validFlag) {
break;
} else {
chain = chain.getNext();
}
}
if (chain == null) {
handle.setMemberDtoList(null);
return handle;
}
}
return null;
}
public static List<VoteCalculateHandle> getHandleList() {
List<VoteCalculateHandle> list = new ArrayList<>();
Reflections reflections = new Reflections(VoteCalculateHandle.class.getPackage().getName());
Set<Class<? extends VoteCalculateHandle>> subTypes = reflections.getSubTypesOf(VoteCalculateHandle.class);
subTypes.forEach(x -> {
try {
VoteCalculateHandle obj = x.newInstance();
list.add(obj);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
return list;
}
public static void main(String[] args) {
VoteCalculateParameterDto parameterDto = new VoteCalculateParameterDto();
parameterDto.setVoteType("0").setVoteRound(1);
VoteCalculateHandle handle = getPlanDto(parameterDto);
VoteCalculateResultDto voteCalculateResultDto = handle.calculate();
System.out.println(JSONObject.toJSONString(voteCalculateResultDto));
}
}