运用场景
APP端需要展示汇总信息,从各个子模块抽取相应数量的数据展示。
各个子模块的功能接口都存在,移动端挨个调用也可完成操作,单本着业务处理服务端处理的原则,我决定合并子模块的结果集,统一调用展示这也是外观模式的变种吧!
业务梳理
- 整合统一的接口处理;
- 工厂模式封装锁需要的结果;
- CyclicBarrier等多线程手段,并行请求接口数据并合并多线程后返回的结果,统一返回移动端。
业务应用–策略模式,工厂模式
- 定义用于请求数据的接口,可拓展参数,此处的请求需要token从外界传入;
public interface UserFunctionStrategy {
/**
* 请求获取用户的功能信息
* @return
*/
Object getUserFunctionFromUrl(String token);
}
- 实现接口,规整请求数据或者业务处理
public class UserFunctionStrategyImpl implements UserFunctionStrategy {
private UserFunctionEnum userFunctionEnum;
@Override
public Object getUserFunctionFromUrl(String token) {
JSONObject requestJson = new JSONObject();
requestJson.put("token", token);
String requestParam = userFunctionEnum.getRequestParam();
if(!StringUtils.isEmpty(requestParam)){
requestJson.put(requestParam.split("_")[0],requestParam.split("_")[1]);
}
return WmsCrawUtil.requestResultData(userFunctionEnum.getUrl(), requestJson);
}
public UserFunctionStrategyImpl(UserFunctionEnum userFunctionEnum){
this.userFunctionEnum = userFunctionEnum;
}
}
- 新增工厂类,初始化各个子模块请求枚举,方便后期调用,避免太长的if-else
public class FunctionFactory {
private static FunctionFactory functionFactory = new FunctionFactory();
private FunctionFactory(){
}
private static Map<String, UserFunctionStrategyImpl> strategyMap = new HashMap<>();
static{
strategyMap.put(UserFunctionEnum.HTXX.getCode(), new UserFunctionStrategyImpl(UserFunctionEnum.HTXX));
strategyMap.put(UserFunctionEnum.LLJH.getCode(), new UserFunctionStrategyImpl(UserFunctionEnum.LLJH));
strategyMap.put(UserFunctionEnum.YHJH.getCode(), new UserFunctionStrategyImpl(UserFunctionEnum.YHJH));
strategyMap.put(UserFunctionEnum.YLLD.getCode(), new UserFunctionStrategyImpl(UserFunctionEnum.YLLD));
strategyMap.put(UserFunctionEnum.ZJD.getCode(), new UserFunctionStrategyImpl(UserFunctionEnum.ZJD));
strategyMap.put(UserFunctionEnum.PDD.getCode(), new UserFunctionStrategyImpl(UserFunctionEnum.PDD));
strategyMap.put(UserFunctionEnum.YHD.getCode(), new UserFunctionStrategyImpl(UserFunctionEnum.YHD));
strategyMap.put(UserFunctionEnum.YTPD.getCode(), new UserFunctionStrategyImpl(UserFunctionEnum.YTPD));
strategyMap.put(UserFunctionEnum.JHRWZX.getCode(), new UserFunctionStrategyImpl(UserFunctionEnum.JHRWZX));
strategyMap.put(UserFunctionEnum.SJRWZX.getCode(), new UserFunctionStrategyImpl(UserFunctionEnum.SJRWZX));
strategyMap.put(UserFunctionEnum.ZXDTZYD.getCode(), new UserFunctionStrategyImpl(UserFunctionEnum.ZXDTZYD));
strategyMap.put(UserFunctionEnum.ZJDRW.getCode(), new UserFunctionStrategyImpl(UserFunctionEnum.ZJDRW));
strategyMap.put(UserFunctionEnum.YSHD.getCode(), new UserFunctionStrategyImpl(UserFunctionEnum.YSHD));
}
public UserFunctionStrategy creator(String type){
return strategyMap.get(type);
}
public static FunctionFactory getInstance(){
return functionFactory;
}
}
- 使用多线程请求获取各个模块数据,避免了繁杂的if-else判断操作
public JSONObject userFunction(Long userId, String type, String token){
long time = System.currentTimeMillis();
List<AppUserRole> appUserRoles = userMenus(userId, type);
JSONObject userFunction = new JSONObject();
//用于检查线程是否结束
final BooleanWithMsg booleanWithMsg = BooleanWithMsg.False("未完成");
//需要等待的线程数
final CyclicBarrier barrier=new CyclicBarrier(appUserRoles.size(), () -> booleanWithMsg.setSuccess(true));
//并行触发任务请求
appUserRoles.forEach(appUserRole -> {
String roleCode = appUserRole.getCode();
executorService.execute(() -> {
Object roleData = callUrlData(roleCode, token);
if(roleData != null){
userFunction.put(roleCode,roleData);
}
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
});
//检查是否结束
while(true){
try {
Thread.sleep(100L);
if(booleanWithMsg.isSuccess() || System.currentTimeMillis()-time > 20000){
return userFunction;
}
} catch (InterruptedException e) {
e.printStackTrace();
return userFunction;
}
}
}
/**
* 获取用于请求数据的工具
* @param code 编码
* @return
*/
private Object callUrlData(String code, String token){
UserFunctionStrategy userFunctionStrategy = FunctionFactory.getInstance().creator(code);
return userFunctionStrategy.getUserFunctionFromUrl(token);
}
- 最后将数统一返回,该方法最大限度优化了数据请求时间,但是也是有水桶效应的,后期再添加相应的子模块可以修改工厂类以及相应的枚举类型就可以完成添加,拓展性增强。