Hi!欢迎光临陕西省的权威思科、华为、Oracle、红帽、深信服、微软认证培训中心!
| 029-88235527
您现在所在位置:首页 > 新闻资讯 > 最新资讯 >

java 代码精简之利用设计模式

发布日期:2020-05-13 14:36:22点击次数:

分享到:
java 代码精简之利用设计模式

10.1.模板方法模式
 
模板方法模式(Template Method Pattern)定义一个固定的算法框架,而将算法的一些步骤放到子类中实现,使得子类可以在不改变算法框架的情况下重定义该算法的某些步骤。
 
普通:
 
@Repository
public class UserValue {
    /** 值操作 */
    @Resource(name = "stringRedisTemplate")
    private ValueOperations<String, String> valueOperations;
    /** 值模式 */
    private static final String KEY_FORMAT = "Value:User:%s";
 
    /** 设置值 */
    public void set(Long id, UserDO value) {
        String key = String.format(KEY_FORMAT, id);
        valueOperations.set(key, JSON.toJSONString(value));
    }
 
    /** 获取值 */
    public UserDO get(Long id) {
        String key = String.format(KEY_FORMAT, id);
        String value = valueOperations.get(key);
        return JSON.parseObject(value, UserDO.class);
    }
 
    ...
}
 
@Repository
public class RoleValue {
    /** 值操作 */
    @Resource(name = "stringRedisTemplate")
    private ValueOperations<String, String> valueOperations;
    /** 值模式 */
    private static final String KEY_FORMAT = "Value:Role:%s";
 
    /** 设置值 */
    public void set(Long id, RoleDO value) {
        String key = String.format(KEY_FORMAT, id);
        valueOperations.set(key, JSON.toJSONString(value));
    }
 
    /** 获取值 */
    public RoleDO get(Long id) {
        String key = String.format(KEY_FORMAT, id);
        String value = valueOperations.get(key);
        return JSON.parseObject(value, RoleDO.class);
    }
 
    ...
}
精简:
public abstract class AbstractDynamicValue<I, V> {
    /** 值操作 */
    @Resource(name = "stringRedisTemplate")
    private ValueOperations<String, String> valueOperations;
 
    /** 设置值 */
    public void set(I id, V value) {
        valueOperations.set(getKey(id), JSON.toJSONString(value));
    }
 
    /** 获取值 */
    public V get(I id) {
        return JSON.parseObject(valueOperations.get(getKey(id)), getValueClass());
    }
 
    ...
 
    /** 获取主键 */
    protected abstract String getKey(I id);
 
    /** 获取值类 */
    protected abstract Class<V> getValueClass();
}
 
@Repository
public class UserValue extends AbstractValue<Long, UserDO> {
    /** 获取主键 */
    @Override
    protected String getKey(Long id) {
        return String.format("Value:User:%s", id);
    }
 
    /** 获取值类 */
    @Override
    protected Class<UserDO> getValueClass() {
        return UserDO.class;
    }
}
 
@Repository
public class RoleValue extends AbstractValue<Long, RoleDO> {
    /** 获取主键 */
    @Override
    protected String getKey(Long id) {
        return String.format("Value:Role:%s", id);
    }
 
    /** 获取值类 */
    @Override
    protected Class<RoleDO> getValueClass() {
        return RoleDO.class;
    }
}
10.2.建造者模式
 
建造者模式(Builder Pattern)将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。
 
普通:
 
public interface DataHandler<T> {
    /** 解析数据 */
public T parseData(Record record);
 
    /** 存储数据 */
public boolean storeData(List<T> dataList);
}
 
public <T> long executeFetch(String tableName, int batchSize, DataHandler<T> dataHandler) throws Exception {
    // 构建下载会话
    DownloadSession session = buildSession(tableName);
 
    // 获取数据数量
    long recordCount = session.getRecordCount();
    if (recordCount == 0) {
        return 0;
    }
 
    // 进行数据读取
    long fetchCount = 0L;
    try (RecordReader reader = session.openRecordReader(0L, recordCount, true)) {
        // 依次读取数据
        Record record;
        List<T> dataList = new ArrayList<>(batchSize);
        while ((record = reader.read()) != null) {
            // 解析添加数据
            T data = dataHandler.parseData(record);
            if (Objects.nonNull(data)) {
                dataList.add(data);
            }
 
            // 批量存储数据
            if (dataList.size() == batchSize) {
                boolean isContinue = dataHandler.storeData(dataList);
                fetchCount += batchSize;
                dataList.clear();
                if (!isContinue) {
                    break;
                }
            }
        }
 
        // 存储剩余数据
        if (CollectionUtils.isNotEmpty(dataList)) {
            dataHandler.storeData(dataList);
            fetchCount += dataList.size();
            dataList.clear();
        }
    }
 
    // 返回获取数量
    return fetchCount;
}
 
 // 使用案例
long fetchCount = odpsService.executeFetch("user", 5000, new DataHandler() {
    /** 解析数据 */
    @Override
public T parseData(Record record) {
        UserDO user = new UserDO();
        user.setId(record.getBigint("id"));
        user.setName(record.getString("name"));
        return user;
    }
 
    /** 存储数据 */
    @Override
public boolean storeData(List<T> dataList) {
        userDAO.batchInsert(dataList);
        return true;
    }
});
精简:
public <T> long executeFetch(String tableName, int batchSize, Function<Record, T> dataParser, Function<List<T>, Boolean> dataStorage) throws Exception {
    // 构建下载会话
    DownloadSession session = buildSession(tableName);
 
    // 获取数据数量
    long recordCount = session.getRecordCount();
    if (recordCount == 0) {
        return 0;
    }
 
    // 进行数据读取
    long fetchCount = 0L;
    try (RecordReader reader = session.openRecordReader(0L, recordCount, true)) {
        // 依次读取数据
        Record record;
        List<T> dataList = new ArrayList<>(batchSize);
        while ((record = reader.read()) != null) {
            // 解析添加数据
            T data = dataParser.apply(record);
            if (Objects.nonNull(data)) {
                dataList.add(data);
            }
 
            // 批量存储数据
            if (dataList.size() == batchSize) {
                Boolean isContinue = dataStorage.apply(dataList);
                fetchCount += batchSize;
                dataList.clear();
                if (!Boolean.TRUE.equals(isContinue)) {
                    break;
                }
            }
        }
 
        // 存储剩余数据
        if (CollectionUtils.isNotEmpty(dataList)) {
            dataStorage.apply(dataList);
            fetchCount += dataList.size();
            dataList.clear();
        }
    }
 
    // 返回获取数量
    return fetchCount;
}
 
 // 使用案例
long fetchCount = odpsService.executeFetch("user", 5000, record -> {
        UserDO user = new UserDO();
        user.setId(record.getBigint("id"));
        user.setName(record.getString("name"));
        return user;
    }, dataList -> {
        userDAO.batchInsert(dataList);
        return true;
    });
普通的建造者模式,实现时需要定义 DataHandler 接口,调用时需要实现 DataHandler 匿名内部类,代码较多较繁琐。而精简后的建造者模式,充分利用了函数式编程,实现时无需定义接口,直接使用 Function 接口;调用时无需实现匿名内部类,直接采用 lambda 表达式,代码较少较简洁。
10.3.代理模式
 
Spring 中最重要的代理模式就是 AOP (Aspect-Oriented Programming,面向切面的编程),是使用 JDK 动态代理和 CGLIB 动态代理技术来实现的。
 
普通:
 
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    /** 用户服务 */
    @Autowired
    private UserService userService;
 
    /** 查询用户 */
    @PostMapping("/queryUser")
    public Result<?> queryUser(@RequestBody @Valid UserQueryVO query) {
        try {
            PageDataVO<UserVO> pageData = userService.queryUser(query);
            return Result.success(pageData);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.failure(e.getMessage());
        }
    }
    ...
}
精简1:
基于  @ControllerAdvice 的异常处理:
 
@RestController
@RequestMapping("/user")
public class UserController {
    /** 用户服务 */
    @Autowired
    private UserService userService;
 
    /** 查询用户 */
    @PostMapping("/queryUser")
    public Result<PageDataVO<UserVO>> queryUser(@RequestBody @Valid UserQueryVO query) {
        PageDataVO<UserVO> pageData = userService.queryUser(query);
        return Result.success(pageData);
    }
    ...
}
 
@Slf4j
@ControllerAdvice
public class GlobalControllerAdvice {
    /** 处理异常 */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public Result<Void> handleException(Exception e) {
        log.error(e.getMessage(), e);
        return Result.failure(e.getMessage());
    }
}
精简2:
基于 AOP 的异常处理:
 
// UserController代码同"精简1"
 
@Slf4j
@Aspect
public class WebExceptionAspect {
    /** 点切面 */
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    private void webPointcut() {}
 
    /** 处理异常 */
    @AfterThrowing(pointcut = "webPointcut()", throwing = "e")
    public void handleException(Exception e) {
        Result<Void> result = Result.failure(e.getMessage());
        writeContent(JSON.toJSONString(result));
    }
    ...
}