设计模式之模板方法模式(Template Method Pattern)


一、概述

    使用一个抽象类将部分的逻辑以具体的方法以及具体的构造子实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑,不同的子类对剩余的逻辑有不同的实现。


优点

  • 利用模板模式将相同处理逻辑的代码抽取到抽象类中,可以提搞代码发重性

  • 将不同的代码放置在不同的子类中,通过对子类的扩展添加新的行为,提搞代码的扩展性

  • 把不变的行为写在父类上,去除子类的重复代码,提供了很好的代码的复用平台,符合开闭原则

缺点

  • 类数目的增加,每个抽象类都要有子类来实现
  • 因为类数目的增加,也间接地导致系统实现的复杂度
  • 继承自身的缺陷,如果抽象类新增了一个方法,所有的子类都要实现一遍

应用场景

  • 一次性实现算法的不变的部分,并将可变的行为留给了子类来实现
  • 各子类中公共的行为被提取出来并集中到一个公共的父类之中,从而避免了代码的重复

二、模板方法模式结构

类图

在这里插入图片描述

结构说明

角色 说明
抽象模板角色(Abstract Template) 定义一个或多个抽象操作(基本操作),以便让子类实现,给出了一个顶级逻辑的骨架,并实现了一个模板方法(具体方法),顶级逻辑也有可能调用一些具体方法
具体模板角色(Concrete Template) 实现父类定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤,每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同

三、案例演示

抽象模板角色类

package com.deepexi.pattern.template;

/**
 * @Author: CaoJun
 * @Description: 抽象模板角色:(Abstract Template)
 * @Create: 2020-01-21 13:22
 **/
public abstract class AbstractTemplate {

    /**
     * 模板方法,顶级逻辑,把基本操作方法组合在一起形成一个总算法或者总行为的方法
     */
    public void templateMethod() {
        abstractMethod();
        doHookMethod();
        concreteMethod();
    }

    protected abstract void abstractMethod();

    /**
     * 钩子方法(可以置换掉)
     */
    protected void doHookMethod() {
        System.out.println();
    }

    /**
     * 具体的方法(不可以被置换掉)
     */
    private void concreteMethod() {
        System.out.println("业务相关代码实现");
    }
}

具体模板角色类

package com.deepexi.pattern.template;

/**
 * @Author: CaoJun
 * @Description: 具体模板角色:(Concrete Template) 可以有多个
 * @Create: 2020-01-21 13:24
 **/
public class ConcreteTemplate extends AbstractTemplate {

    @Override
    protected void abstractMethod() {
        System.out.println("抽象方法的实现");
    }

    /**
     * 钩子方法:替换父类可变的部分,但是子类不可以改变模板方法所代表的顶级逻辑
     */
    @Override
    protected void doHookMethod() {
        System.out.println("钩子方法:替换父类可变的部分");
    }
}

客户端测试


package com.deepexi.pattern.template;

/**
 * @Author: CaoJun
 * @Description: 客户端测试
 * @Create: 2020-01-21 13:28
 **/
public class Client {

    public static void main(String[] args) {
        AbstractTemplate template = new ConcreteTemplate();
        template.templateMethod();
    }
}

业务场景案例

约束 ORM 逻辑的接口

package com.deepexi.pattern.template.demo;

import java.sql.ResultSet;

/**
 * @Author: CaoJun
 * @Description: 约束 ORM 逻辑的接口
 * @Create: 2020-01-21 14:36
 **/
public interface RowMapper<T> {

    T mapRow(ResultSet rs, int rowNum) throws Exception;
}

封装了所有处理流程的抽象类

package com.deepexi.pattern.template.demo;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: CaoJun
 * @Description: 封装了所有处理流程的抽象类
 * @Create: 2020-01-21 14:37
 **/
public abstract class JdbcTemplate {

    private DataSource dataSource;

    public JdbcTemplate(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public List<?> excuteQuery(String sql, RowMapper<?> rowMapper, Object[] values) {

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet rs = null;
        try {
            // 1、获取连接
            connection = this.createConnection();
            // 2、创建语句集
            preparedStatement = this.createPreparedStatement(connection, sql);
            // 3、执行语句集
            rs = this.excuteQuery(preparedStatement, values);
            // 4、处理结果集并返回
            return this.handleResultSet(rs, rowMapper);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            try {
                // 5、关闭结果集
                if (rs != null)
                    this.closeResultSet(rs);
                // 6、关闭语句集
                if (preparedStatement != null)
                    this.closePreparedStatement(preparedStatement);
                // 7、关闭连接
                if (connection != null)
                    this.closeConnection(connection);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private Connection createConnection() throws SQLException {
        return dataSource.getConnection();
    }

    private PreparedStatement createPreparedStatement(Connection connection, String sql) throws SQLException {
        return connection.prepareStatement(sql);
    }

    private ResultSet excuteQuery(PreparedStatement preparedStatement, Object[] values) throws SQLException {
        for (int i = 0; i < values.length; i++) {
            preparedStatement.setObject(i, values[i]);
        }

        return preparedStatement.executeQuery();
    }

    private List<?> handleResultSet(ResultSet rs, RowMapper<?> rowMapper) throws Exception {

        List<Object> result = new ArrayList<>();
        int rowNum = 1;
        while (rs.next()) {
            result.add(rowMapper.mapRow(rs, ++rowNum));
        }

        return result;
    }

    private void closeResultSet(ResultSet rs) throws SQLException {
        rs.close();
    }

    private void closePreparedStatement(PreparedStatement preparedStatement) throws SQLException {
        preparedStatement.close();
    }

    private void closeConnection(Connection connection) throws SQLException {
        connection.close();
    }
}

模拟模型对象

package com.deepexi.pattern.template.demo;

import lombok.Data;

import java.util.Date;

/**
 * @Author: CaoJun
 * @Description:
 * @Create: 2020-01-21 14:50
 **/
@Data
public class Person {

    private String name;

    private int sex;

    private String character;

    private Date birthday;
}

模式数据访问层

package com.deepexi.pattern.template.demo;

import javax.sql.DataSource;
import java.util.List;

/**
 * @Author: CaoJun
 * @Description: Person 数据访问层
 * @Create: 2020-01-21 14:51
 **/
public class PersonDao extends JdbcTemplate {


    public PersonDao(DataSource dataSource) {
        super(dataSource);
    }

    public List<Person> selectAll() {
        String sql = "SELECT * FROM tb_person;";


        return (List<Person>) super.excuteQuery(sql, (RowMapper<Person>) (rs, rowNum) -> {
            Person person = new Person();
            person.setName(rs.getString("name"));
            person.setBirthday(rs.getDate("date"));
            person.setCharacter(rs.getString("character"));
            person.setSex(rs.getInt("sex"));
            return person;
        }, null);
    }
}

测试

package com.deepexi.pattern.template.demo;

import java.util.List;

/**
 * @Author: CaoJun
 * @Description: 客户端测试
 * @Create: 2020-01-21 15:05
 **/
public class ClientTest {
    public static void main(String[] args) {
        // 会出现空指针,使用时候可以注入个 DataSource
        PersonDao personDao = new PersonDao(null);
        List<Person> personList = personDao.selectAll();
        System.out.println(personList);
    }
}
发布了17 篇原创文章 · 获赞 3 · 访问量 544

猜你喜欢

转载自blog.csdn.net/weixin_38251871/article/details/104062437