《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

相关文章
|
20小时前
|
Java 编译器
滚雪球学Java(36):玩转Java方法重载和可变参数,让你的代码更灵活
【5月更文挑战第11天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
5 0
滚雪球学Java(36):玩转Java方法重载和可变参数,让你的代码更灵活
|
2天前
|
Java 测试技术
如何提高Java代码的可读性
Java是一种常用的编程语言,但是写出易懂且可读性高的代码却是一项挑战。本文将分享一些技巧和建议,帮助您提高Java代码的可读性和可维护性。
|
5天前
|
NoSQL Dubbo Java
StringBoot编程式事务与声明式事务java工程师面试突击第一季
StringBoot编程式事务与声明式事务java工程师面试突击第一季
|
6天前
|
Java Kotlin
java调用kotlin代码编译报错“找不到符号”的问题
java调用kotlin代码编译报错“找不到符号”的问题
17 10
|
6天前
|
前端开发 Java Spring
Java Web ——MVC基础框架讲解及代码演示(下)
Java Web ——MVC基础框架讲解及代码演示
13 1
|
6天前
|
设计模式 前端开发 网络协议
Java Web ——MVC基础框架讲解及代码演示(上)
Java Web ——MVC基础框架讲解及代码演示
8 0
|
6天前
|
Java
Java的取余如何编写代码
【5月更文挑战第9天】Java的取余如何编写代码
22 5
|
6天前
|
Java
代码实例演示Java字符串与输入流互转
代码实例演示Java字符串与输入流互转
10 1
|
6天前
|
存储 安全 Java
掌握8条泛型规则,打造优雅通用的Java代码
掌握8条泛型规则,打造优雅通用的Java代码
掌握8条泛型规则,打造优雅通用的Java代码
|
6天前
|
Java 程序员 图形学
程序员教你用代码制作飞翔的小鸟--Java小游戏,正好拿去和给女神一起玩
《飞扬的小鸟》Java实现摘要:使用IntelliJ IDEA和JDK 16开发,包含小鸟类`Bird`,处理小鸟的位置、速度和碰撞检测。代码示例展示小鸟图像的加载、绘制与旋转。同时有`Music`类用于循环播放背景音乐。游戏运行时检查小鸟是否撞到地面、柱子或星星,并实现翅膀煽动效果。简单易懂,可直接复制使用。