java设计模式之模板模式以及钩子方法使用

1、使用背景

  模板方法模式是通过把不变行为搬到超类,去除子类里面的重复代码提现它的优势,它提供了一个很好的代码复用平台。当不可变和可变的方法在子类中混合在一起的时候,

不变的方法就会在子类中多次出现,这样如果摸个方法需要修改则需要修改很多个,虽然这个这个问题在设计之初就应该想好。这个时候模板方法模式就起到了作用了,

通过模板方法模式把这些重复出现的方法搬到单一的地方,这样就可以帮助子类摆脱重复不变的纠缠。

2、已Spring中的  JdbcTemplate 使用模板模式为例  说明其优越之处;

方法 execute(StatementCallback<T> sc) 方法公共方法,里边封装了可复用代码;

参数StatementCallback是一个接口 接口方法是 doInStatement() 该方法是实现不同操作的方法;也就是不同的实现在这里呈现;

public <L> L execute(StatementCallback<L> action)
    {
          
        try{ 
                    1. 加载驱动 
                    2. 建立连接 
                    3. 获取Statement stmt
@Override
public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {
    Assert.notNull(sql, "SQL must not be null");
    Assert.notNull(rse, "ResultSetExtractor must not be null");
    if (logger.isDebugEnabled()) {
        logger.debug("Executing SQL query [" + sql + "]");
    }
    //匿名内部类
    class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
        @Override
        public T doInStatement(Statement stmt) throws SQLException {
            ResultSet rs = null;
            try {
                rs = stmt.executeQuery(sql);
                ResultSet rsToUse = rs;
                if (nativeJdbcExtractor != null) {
                    rsToUse = nativeJdbcExtractor.getNativeResultSet(rs);
                }
                return rse.extractData(rsToUse);
            }
            finally {
                JdbcUtils.closeResultSet(rs);
            }
        }
        @Override
        public String getSql() {
            return sql;
        }
    }
    //真正执行的方法
    return execute(new QueryStatementCallback());
}

调用query方法的时候 会执行execute方法,该方法为模板方法,然后因为该方法内部调用传入的 StatementCallback 接口的 doInStatement 方法 但是该方法可以在query方法中通过传入匿名内部类,自定义使用; 完全符合模板模式的使用;

1、使用钩子方法对模板不同行为进行控制

下面以一个汽车的例子来说明钩子方法的使用:

public abstract class HummerModel {
    protected abstract void start(); //发动
    protected abstract void stop();  //停止
    protected abstract void alarm(); //鸣笛
    protected abstract void engineBoom(); //轰鸣
    final public void run() { //车总归要跑
        this.start();
        this.engineBoom();
        if(this.isAlarm()) {//想让它叫就叫,不想就不叫        
            this.alarm();
        }
        this.stop();
    }
    protected boolean isAlarm() { //我们加了一个判断方法,默认返回true
        return true;
    }
}
public class HummerH1 extends HummerModel {
 
    private boolean alarmFlag = true; //判断标记
    @Override
    public void start() {
        System.out.println("H1发动……");
    }
 
    @Override
    public void stop() {
        System.out.println("H1停止……");
    }
 
    @Override
    public void alarm() {
        System.out.println("H1鸣笛……");
    }
 
    @Override
    public void engineBoom() {
        System.out.println("H1轰鸣……");
    }
    
    @Override
    protected boolean isAlarm() { //覆写isAlarm方法,返回判断标记
        return this.alarmFlag;
    }
    
    public void setAlarm(boolean isAlarm) { //设置判断标记
        this.alarmFlag = isAlarm;
    }
    
}
这段代码中,我们在模板方法中增加了判断标记,然后子类对外提供一个public接口setAlarm来让外界设置这个判断标记,这个判断标记就像是开关一样,想让它ture和false都行。
这个isAlarm方法俗称钩子方法。有了钩子方法的模板方法模式才算完美,使得我们的控制行为更加的主动,更加的灵活。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏轮子工厂

5. 很“迷”的字符与字符串

最近一直在为自己的浏览量而担忧啦,都快被厂长大人约谈了……我真的有尽力在写稿子哦,所以也请各位老铁,如果觉得我的文章还不错就转发到朋友圈或者微信群之类的,让更多...

1192
来自专栏xiaoxi666的专栏

状态机编程思想(1):括号内外字符串统计

我们拿到这个问题时,第一感觉往往是顺序遍历字符串,并检测左右相邻字符是否满足边界条件,从而进行分支处理。但是这样做有以下棘手之处:

983
来自专栏python3

python3--面向对象--综合练习

3  解释生成器(generator)与函数的不同,并实现且使用简单generator

1342
来自专栏技术总结

iOS不可错过的关键字

建议查看原文:https://www.jianshu.com/p/dce05b24d288(不定时更新)

853
来自专栏技术/开源

从C#到TypeScript - Promise

从C#到TypeScript - Promise 背景 相信之前用过JavaScript的朋友都碰到过异步回调地狱(callback hell),N多个回调的嵌...

2048
来自专栏腾讯Bugly的专栏

内存泄露从入门到精通三部曲之基础知识篇

1 首先以一个内存泄露实例来开始本节基础概念的内容: 实例1:(单例导致内存对象无法释放而泄露) ? ? 可以看出ImageUtil这个工具类是一个单例,并引...

3346
来自专栏java一日一条

代码优化那些事

/**************************************************************************/

653
来自专栏博客园

MSIL学习------从HelloWorld开始

  前段时间突然想搞搞IL语言,于是在博客园中找到了包建强前辈关于IL的文章学习,并且在包前辈博客里看到了09年他与赵劼前辈关于是否有必要学习IL语言的争论,作...

1423
来自专栏Android开发指南

编码规范

3368
来自专栏IT派

全面深入理解Python面向对象编程

面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。

1182

扫码关注云+社区

领取腾讯云代金券