《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

相关文章
|
18天前
|
Java 测试技术 应用服务中间件
常见 Java 代码缺陷及规避方式(下)
常见 Java 代码缺陷及规避方式(下)
47 0
|
20天前
|
Java
Java中ReentrantLock释放锁代码解析
Java中ReentrantLock释放锁代码解析
25 8
|
21天前
|
设计模式 存储 Java
23种设计模式,备忘录模式的概念优缺点以及JAVA代码举例
【4月更文挑战第9天】备忘录模式是一种行为设计模式,它能在不破坏对象封装的前提下,捕获并保存对象的当前状态,以便后面可以恢复到这个状态。
26 0
|
5天前
|
SQL Java 数据库
java代码中调用dao层查询接口,代码没有返回数据,打印出的sql查出了数据
java代码中调用dao层查询接口,代码没有返回数据,打印出的sql查出了数据
10 1
|
5天前
|
安全 Java 开发者
Java编程:深入探索其原理、特性与实战代码
Java编程:深入探索其原理、特性与实战代码
10 1
|
6天前
|
存储 算法 Java
滚雪球学Java(20):Java泛型与枚举:提升代码灵活性与可读性
【4月更文挑战第9天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
19 1
滚雪球学Java(20):Java泛型与枚举:提升代码灵活性与可读性
|
9天前
|
Java 测试技术 持续交付
云效产品使用常见问题之通过流水线构建的java代码,在docker文件里拿到失败如何解决
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
15天前
|
Java 测试技术
滚雪球学Java(12):JavaSE-if条件语句入门指南:掌握代码分支流程!
【4月更文挑战第1天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
50 1
滚雪球学Java(12):JavaSE-if条件语句入门指南:掌握代码分支流程!
|
17天前
|
人工智能 Kubernetes Java
Java开发工程师如何紧跟技术前沿对于保持专业竞争力、提升工作效率以及适应行业发展?
【4月更文挑战第4天】Java开发工程师如何紧跟技术前沿对于保持专业竞争力、提升工作效率以及适应行业发展?
21 4
|
18天前
|
Java
与JShell一起舞动代码的魔法:Java9交互式编程体验
与JShell一起舞动代码的魔法:Java9交互式编程体验
31 0