《Java工程师必读手册》——Java极客主义系列——Java代码精简之道(9)

简介: 《Java工程师必读手册》——Java极客主义系列——Java代码精简之道(9)

接上篇:https://developer.aliyun.com/article/1227318?spm=a2c6h.13148508.setting.20.48e04f0eaBVGWH


十、 利用设计模式

 

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;

    }

}

 

 

 

2. 访问者模式

 

访问者模式(Visitor),封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

 

普通

 

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表达式,代码较少较简洁。

 

3. 代理模式

 

Spring中最重要的代理模式就是AOPAspect-Oriented Programming,面向切面的编程,是使用JDK动态代理和CGLIB动态代理技术来实现的。

 

普通

 

image.png 

 

精简1

 

基于@ControllerAdvice的异常处理:

 

image.png 

 

精简2

 

基于AOP的异常处理:

 

image.png


  接下篇:https://developer.aliyun.com/article/1227315?groupCode=java

相关文章
|
4月前
|
Java 开发工具
【Azure Storage Account】Java Code访问Storage Account File Share的上传和下载代码示例
本文介绍如何使用Java通过azure-storage-file-share SDK实现Azure文件共享的上传下载。包含依赖引入、客户端创建及完整示例代码,助你快速集成Azure File Share功能。
411 5
|
4月前
|
Java 数据处理 API
为什么你的Java代码应该多用Stream?从循环到声明式的思维转变
为什么你的Java代码应该多用Stream?从循环到声明式的思维转变
300 115
|
4月前
|
安全 Java 编译器
为什么你的Java代码需要泛型?类型安全的艺术
为什么你的Java代码需要泛型?类型安全的艺术
215 98
|
4月前
|
Java 编译器 API
java最新版和java8的区别,用代码展示
java最新版和java8的区别,用代码展示
366 43
|
4月前
|
安全 Java 容器
告别空指针噩梦:Optional让Java代码更优雅
告别空指针噩梦:Optional让Java代码更优雅
430 94
|
4月前
|
安全 Java 容器
告别繁琐判空:Optional让你的Java代码更优雅
告别繁琐判空:Optional让你的Java代码更优雅
|
5月前
|
IDE Java 关系型数据库
Java 初学者学习路线(含代码示例)
本教程为Java初学者设计,涵盖基础语法、面向对象、集合、异常处理、文件操作、多线程、JDBC、Servlet及MyBatis等内容,每阶段配核心代码示例,强调动手实践,助你循序渐进掌握Java编程。
644 3
|
5月前
|
安全 Java 应用服务中间件
Spring Boot + Java 21:内存减少 60%,启动速度提高 30% — 零代码
通过调整三个JVM和Spring Boot配置开关,无需重写代码即可显著优化Java应用性能:内存减少60%,启动速度提升30%。适用于所有在JVM上运行API的生产团队,低成本实现高效能。
605 3
|
5月前
|
Java
java入门代码示例
本文介绍Java入门基础,包含Hello World、变量类型、条件判断、循环及方法定义等核心语法示例,帮助初学者快速掌握Java编程基本结构与逻辑。
480 0