- 模板方法模式 模板方法模式(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 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 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 getValueClass() { return RoleDO.class; } }
-
访问者模式 访问者模式(Visitor),封装一些作用于某种数据结构的各元素的操作,它可以在不 改变数据结构的前提下定义作用于这些元素的新的操作。 普通: public interface DataHandler { /** 解析数据 */ public T parseData(Record record);
/** 存储数据 */ public boolean storeData(List dataList); } public long executeFetch(String tableName, int batchSize, DataHandler 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 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 dataList) { userDAO.batchInsert(dataList); return true; } }); 精简: public long executeFetch(String tableName, int batchSize, Function<Record, T> dataParser, Function<List , 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 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 表达式,代码较少较简洁。
3. 代理模式
Spring 中最重要的代理模式就是 AOP(Aspect-Oriented Programming,面向切面
的编程),是使用 JDK 动态代理和 CGLIB 动态代理技术来实现的。
普通:
精简 1:
基于@ControllerAdvice 的异常处理:
精简 2:
基于 AOP 的异常处理:
以上内容摘自《Java工程师必读手册》电子书,点击https://developer.aliyun.com/ebook/download/7780
可下载完整版