本文节选自《设计模式就该这样学》

通常的模板办法模式中会设计一个abstract的形象办法,交给它的子类实现,这个办法称为模板办法。而钩子办法,是对于形象办法或者接口中定义的办法的一个空实现,也是模板办法模式的一种实现形式。

1 模板办法模式中的钩子办法

咱们以网络课程创立流程为例:公布预习材料 → 制作课件PPT → 在线直播 → 提交课堂笔记 → 提交源码 → 安排作业 → 查看作业。首先创立AbastractCourse抽象类。

public abstract class AbastractCourse {        public final void createCourse(){        //1.公布预习材料        postPreResoucse();                //2.制作课件PPT        createPPT();                //3.在线直播        liveVideo();                //4.上传课后材料        postResource();                //5.安排作业        postHomework();                if(needCheckHomework()){            checkHomework();        }    }    protected abstract void checkHomework();    //钩子办法    protected boolean needCheckHomework(){return  false;}    protected void postHomework(){        System.out.println("安排作业");    }    protected void postResource(){        System.out.println("上传课后材料");    }    protected void liveVideo(){        System.out.println("直播授课");    }    protected void createPPT(){        System.out.println("制作课件");    }    protected void postPreResoucse(){        System.out.println("公布预习材料");    }}

下面代码中有个钩子办法,可能有些小伙伴不是太了解,在此笔者稍做解释。设计钩子办法的次要目标是干涉执行流程,使得管制行为流程更加灵便,更符合实际业务的需要。钩子办法的返回值个别为适宜条件分支语句的返回值(如boolean、int等)。小伙伴们能够依据本人的业务场景决定是否须要应用钩子办法。
而后创立JavaCourse类。

public class JavaCourse extends AbastractCourse {    private boolean needCheckHomework = false;    public void setNeedCheckHomework(boolean needCheckHomework) {        this.needCheckHomework = needCheckHomework;    }    @Override    protected boolean needCheckHomework() {        return this.needCheckHomework;    }    protected void checkHomework() {        System.out.println("查看Java作业");    }}

创立PythonCourse类。

public class PythonCourse extends AbastractCourse {    protected void checkHomework() {        System.out.println("查看Python作业");    }}

最初编写客户端测试代码。

    public static void main(String[] args) {        System.out.println("=========架构师课程=========");        JavaCourse java = new JavaCourse();        java.setNeedCheckHomework(false);        java.createCourse();        System.out.println("=========Python课程=========");        PythonCourse python = new PythonCourse();        python.createCourse();    }        

通过这样一个案例,置信小伙伴们对模板办法模式有了一个根本的印象。为了加深了解,咱们联合一个常见的业务场景进行介绍。

2 应用模板办法模式重构JDBC业务操作

创立一个模板类JdbcTemplate,封装所有的JDBC操作。以查问为例,每次查问的表都不同,返回的数据结构也就都不一样。咱们针对不同的数据,都要封装成不同的实体对象。而每个实体封装的逻辑都是不一样的,但封装前和封装后的解决流程是不变的,因而,能够应用模板办法模式设计这样的业务场景。首先创立束缚ORM逻辑的接口RowMapper。

/** * ORM映射定制化的接口 * Created by Tom. */public interface RowMapper<T> {    T mapRow(ResultSet rs,int rowNum) throws Exception;}

而后创立封装了所有解决流程的抽象类JdbcTemplate。

public abstract class JdbcTemplate {    private DataSource dataSource;    public JdbcTemplate(DataSource dataSource) {        this.dataSource = dataSource;    }    public final List<?> executeQuery(String sql,RowMapper<?> rowMapper,Object[] values){        try {            //1.获取连贯            Connection conn = this.getConnection();            //2.创立语句集            PreparedStatement pstm = this.createPrepareStatement(conn,sql);            //3.执行语句集            ResultSet rs = this.executeQuery(pstm,values);            //4.处理结果集            List<?> result = this.parseResultSet(rs,rowMapper);            //5.敞开后果集            rs.close();            //6.敞开语句集            pstm.close();            //7.敞开连贯            conn.close();            return result;        }catch (Exception e){            e.printStackTrace();        }        return null;    }    private List<?> parseResultSet(ResultSet rs, RowMapper<?> rowMapper) throws Exception {        List<Object> result = new ArrayList<Object>();        int rowNum = 0;        while (rs.next()){            result.add(rowMapper.mapRow(rs,rowNum++));        }        return result;    }    private ResultSet executeQuery(PreparedStatement pstm, Object[] values) throws SQLException {        for (int i = 0; i < values.length; i++) {            pstm.setObject(i,values[i]);        }        return pstm.executeQuery();    }    private PreparedStatement createPrepareStatement(Connection conn, String sql) throws SQLException {        return conn.prepareStatement(sql);    }    private Connection getConnection() throws SQLException {        return this.dataSource.getConnection();    }}

创立实体对象Member类。

public class Member {    private String username;    private String password;    private String nickname;    private int age;    private String addr;    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    public String getNickname() {        return nickname;    }    public void setNickname(String nickname) {        this.nickname = nickname;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getAddr() {        return addr;    }    public void setAddr(String addr) {        this.addr = addr;    }}

创立数据库操作类MemberDao。

public class MemberDao extends JdbcTemplate {    public MemberDao(DataSource dataSource) {        super(dataSource);    }    public List<?> selectAll(){        String sql = "select * from t_member";        return super.executeQuery(sql, new RowMapper<Member>() {            public Member mapRow(ResultSet rs, int rowNum) throws Exception {                Member member = new Member();                //字段过多,原型模式                member.setUsername(rs.getString("username"));                member.setPassword(rs.getString("password"));                member.setAge(rs.getInt("age"));                member.setAddr(rs.getString("addr"));                return member;            }        },null);    }}

最初编写客户端测试代码。

public static void main(String[] args) {        MemberDao memberDao = new MemberDao(null);        List<?> result = memberDao.selectAll();        System.out.println(result);}

心愿通过这两个案例的业务场景剖析,小伙伴们可能对模板办法模式有更深的了解。

【举荐】Tom弹架构:珍藏本文,相当于珍藏一本“设计模式”的书

本文为“Tom弹架构”原创,转载请注明出处。技术在于分享,我分享我高兴!
如果本文对您有帮忙,欢送关注和点赞;如果您有任何倡议也可留言评论或私信,您的反对是我保持创作的能源。关注微信公众号『 Tom弹架构 』可获取更多技术干货!