• Java模板方法模式源码剖析及使用场景


    一、原理与通俗理解

    模板方法模式定义了一个算法的骨架,将某些步骤推迟到子类中实现。模板方法定义一个算法的骨架,将一些步骤的实现延迟到子类中完成。这样做的目的是确保算法的结构保持不变,同时又可以为不同的子类提供特定步骤的实现。

    比如去餐馆吃饭,餐馆有固定的流程(下单->上菜->吃饭->付款),这就是模板方法。但对于不同的顾客,他们点的菜不同(重写了上菜这一步骤)。

    二、案例演示

    1. 员工审核系统需求
      1. 收集员工信息
      2. 验证员工资格
      3. 核心决策是否雇佣
      4. 雇佣或拒绝员工
    // 抽象类 - 模板方法
    abstract class EmployeeApprover {
        // 模板方法
        public final void processRequest(EmployeeRequest request) {
            collectEmployeeInfo(request); // 1
            verifyEmployeeInfo(request); // 2
            if (approveEmployee(request)) { // 3
                hireEmployee(request); // 4
            } else {
                rejectEmployee(request); // 4
            }
        }
    
        // 收集员工信息 - 由子类实现
        protected abstract void collectEmployeeInfo(EmployeeRequest request);
    
        // 验证员工资格 - 由子类实现
        protected abstract void verifyEmployeeInfo(EmployeeRequest request);
    
        // 核心决策 - 由子类实现
        protected abstract boolean approveEmployee(EmployeeRequest request);
    
        // 具体雇佣步骤
        private void hireEmployee(EmployeeRequest request) {
            System.out.println("已雇佣员工: " + request.getName());
        }
    
        // 具体拒绝步骤
        private void rejectEmployee(EmployeeRequest request) {
            System.out.println("已拒绝员工: " + request.getName());
        }
    }
    
    // 具体子类 - 实现抽象方法
    class ITEmployeeApprover extends EmployeeApprover {
        @Override
        protected void collectEmployeeInfo(EmployeeRequest request) {
            // 收集IT员工信息
        }
    
        @Override
        protected void verifyEmployeeInfo(EmployeeRequest request) {
            // 验证IT员工资格
        }
    
        @Override
        protected boolean approveEmployee(EmployeeRequest request) {
            // 审核IT员工是否合格
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    1. CRM系统订单处理需求
      1. 收集订单信息
      2. 验证订单信息
      3. 核心决策是否发货
      4. 发货或拒绝订单
    // 抽象类 - 模板方法
    abstract class OrderProcessor {
        // 模板方法
        public final void processOrder(Order order) {
            collectOrderInfo(order); // 1
            verifyOrderInfo(order); // 2
            if (approveOrder(order)) { // 3
                shipOrder(order); // 4
            } else {
                rejectOrder(order); // 4
            }
        }
    
        // 收集订单信息 - 由子类实现
        protected abstract void collectOrderInfo(Order order);
    
        // 验证订单信息 - 由子类实现
        protected abstract void verifyOrderInfo(Order order);
    
        // 核心决策 - 由子类实现 
        protected abstract boolean approveOrder(Order order);
    
        // 具体发货步骤
        private void shipOrder(Order order) {
            System.out.println("已发货订单: " + order.getId());
        }
    
        // 具体拒绝步骤
        private void rejectOrder(Order order) {
            System.out.println("已拒绝订单: " + order.getId());
        }
    }
    
    // 具体子类 - 实现抽象方法
    class OnlineOrderProcessor extends OrderProcessor {
        @Override
        protected void collectOrderInfo(Order order) {
            // 收集在线订单信息
        }
    
        @Override
        protected void verifyOrderInfo(Order order) {
            // 验证在线订单信息
        }
    
        @Override
        protected boolean approveOrder(Order order) {
            // 审核在线订单是否合格
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    三、Java源码中的模板方法模式

    1. InputStream抽象类

    InputStream定义了读取数据的标准方法read(),而具体的读取方式由子类实现。

    public abstract class InputStream implements Closeable {
        public abstract int read() throws IOException;
        
        public int read(byte b[]) throws IOException {
            return read(b, 0, b.length);
        }
        
        public int read(byte b[], int off, int len) throws IOException {
            // 模板方法
        }
        
        // 其他方法...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    1. AbstractList抽象类

    AbstractList提供了模板方法addAll()用于批量添加元素,而具体的添加逻辑由子类实现。

    public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
        public boolean addAll(Collection<? extends E> c) {
            // 模板方法
            return batchOperation(c, true);
        }
        
        private boolean batchOperation(...) {
            // ...
            for (E e : c)
                result = add(e); // 调用抽象方法
        }
    
        public abstract boolean add(E e); // 抽象方法,子类实现
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. Spring JdbcTemplate

    JdbcTemplate使用模板方法模式对底层的JDBC操作进行封装,开发者只需实现回调接口即可。以query方法为例:

    public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {  
    
        public <T> T query(String sql, Object[] args, ResultSetExtractor<T> rse) throws DataAccessException {
            // 模板方法
            return query(sql, newArgPreparedStatementSetter(args), rse);
        }
    
        // 实际的查询逻辑
        private <T> T query(PreparedStatementCreator psc, ResultSetExtractor<T> rse) throws DataAccessException {
            // 具体的数据库操作...
            rse.extractData(rs); // 调用回调接口
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    四、总结优缺点以及使用经验

    优点:

    1. 封装不变部分,扩展可变部分,代码复用性好
    2. 父类调用子类操作,通过子类扩展增强功能
    3. 符合开闭原则和里氏替换原则

    缺点:

    1. 每个不同的实现都需要定义一个子类,类的个数可能过多
    2. 父类和子类之间存在潜在的扩展性限制
    3. 编写过程复杂,逻辑较难理解

    使用经验:

    1. 适用于复杂流程,有固定不变的算法骨架和某些可变的细节
    2. 需要先分清楚算法固定部分和可变部分
    3. 体现了模板模式的核心思想"继承 + 多态"
    4. 在框架设计中是常用的模式,可以提高代码的复用性
    5. 不建议过度使用,需要权衡利弊,避免类膨胀

    模板方法模式是一种典型的通过交换算法步骤扩展功能的设计模式,适用于算法骨架固定,某些步骤需要不同实现的场景。恰当使用可以提高代码复用性和系统扩展性。

  • 相关阅读:
    【解决】Splunk Lookup table owner: nobody
    【LeetCode力扣】234 快慢指针 | 反转链表 | 还原链表
    bugku-杂项-社工进阶收集
    PWM配置智能小车电机-让小车动起来
    区分dom对象和jQuery对象、jQuery对象的本质、jQuery对象和dom对象使用的区别和相互转换
    【C++】-还在玩普通的类吗,这里面有好几种特殊的类的设计,快进来看看
    【Springboot】整合kafka
    类型体系与基本数据类型(第五节)
    select...for update到底是加了行锁,还是表锁?
    代码随想录 动态规划Ⅶ
  • 原文地址:https://blog.csdn.net/weixin_44716935/article/details/136600134