模板方法模式(模板方法设计模式)与回调机制解析

模板方法是什么?

模板方法模式在一个方法中定义一个算法的骨架,将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体的结构情况下,重新定义算法中的某些步骤。

public  abstract class AbstractClass {
    public void templateMedhod(){
    	//一堆代码,通用的代码
        method1();
       //一堆代码,通用的代码
        method2();
       //一堆代码,通用的代码
        method3();
        
    }
    protected abstract void method3();

    protected abstract void method2();

    protected abstract void method1();
}
public class ConcreteClass1 extends AbstractClass {

    @Override
    protected void method3() {
        System.out.println("3");
    }

    @Override
    protected void method2() {
        System.out.println("2");
    }

    @Override
    protected void method1() {
        System.out.println("1");
    }
}
public class ConcreteClass2 extends AbstractClass {

    @Override
    protected void method3() {
        System.out.println("3");
    }

    @Override
    protected void method2() {
        System.out.println("2");
    }

    @Override
    protected void method1() {
        System.out.println("1");
    }
}
public class client {
    public static void main(String[] args) {
        AbstractClass tm = new ConcreteClass1();
        tm.templateMedhod();
    }
}

模式很简单,就是一个抽象类(AbstractClass ),定义方法。在具体实现类中进行实现。
具体实现类可以有一个,也可以有很多个。例如代码中的(ConcreteClass1,ConcreteClass2)

从代码中,我们就能看到,模板方法模式,复用和扩展。

我们可以将通用的代码,在templateMedhod 中书写。 对于每个模块的差异,分别进行实现。

回调机制

我们在开发过程中,常常也会用到回调机制。
回调机制有两种,一种是同步回调,一种是异步回调。

a调用b,b反过来调用a,就是回调。
在c中,可以用函数指针,java中需要使用回调函数的类对象。

代码示例:
例如张三给李四打电话:

定义一个回调接口

public interface ICallBack {
    void methodCallback();
}

张三

public class Zhangsan {

    public static void main(String[] args) {
        Zhangsan aClass = new Zhangsan();
        aClass.phoneCall();
    }

    public void phoneCall() {
        System.out.println("找到lisi");
        Lisi lisi = new Lisi();
        System.out.println("开始打电话");
        lisi.process(new ICallBack() {
            @Override
            public void methodCallback() {
                System.out.println("张三这也接通了");
            }
        });
    }


}

李四

public class Lisi {

	//用来处理电话
    public void process(ICallBack callBack){

        System.out.println("正在通话中。。。");
        System.out.println("等2s种后");
        try {
            Thread.sleep(1000*2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("lisi接电话了");
        callBack.methodCallback();

    }
}

运行结果是:

找到lisi
开始打电话
正在通话中。。。
等2s种后
lisi接电话了
张三这也接通了

同步回调指在函数返回之前执行回调函数;异步回调指的是在函数返回之后执行回调函数。
上面这种是同步回调函数。

框架举例JDBCTEMPLATE:

jdbc操作数据库很繁琐。有很多步骤。
//1.创建datasource
//2.获取connection
//3.创建statement
//4 执行sql语句
//5 处理resultset
//6 关闭资源对象

当我们使用jdbctemplate的时候,直接执行excute方法就行了。只需执行两个步骤就行了。

 //获取template实例
private JdbcTemplate jdbcTemplate=ioc.getBean(JdbcTemplate.class);
//执行sql语句
 String sql = "select * from Order";
 jdbcTemplate.execute(sql);

其他的重复步骤 封装到了框架中。

假设我们是设计者,那些重复的步骤封装。我们可以使用模板方法模式:
我们定义一个AbstractJdbcTemplate类

public abstract class AbstractJdbcTemplate{
 
    @Autowired
    private DataSource dataSource;
    
    public final Object execute(String sql) {  
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            connection = dataSource.getConnection();
            statement = connection.createStatement();
            resultSet = statement.executeQuery(sql);
            //处理结果使用模板方法
            Object object = handleResultSet(resultSet);         
            return object;
        } catch (SQLException e) {
            System.out.print(e);
        } finally {
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                }
            }
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                }
            }
        }
        return null;
    }
    
    protected abstract Object handleResultSet(ResultSet rs) throws SQLException;  
}

handleResultSet用来处理 ResultSet
具体实现我们使用一个类来继承AbstractJdbcTemplate

public class OrderJdbcTemplate extends AbstractJdbcTemplate{
 
    @Override
    protected Object handleResultSet(ResultSet rs) throws SQLException {
 
        List<Order> orders = new ArrayList<Order>();
        while (rs.next()) {
            Order order = new Order(rs.getLong("id"), rs.getString("order_number"), rs.getString("delivery_address"));
            orders.add(order);
        }
        return orders;
    }
}

ResultSet 中的结果,并构建了业务对象进行返回。

我们再使用 OrderJdbcTemplate 执行目标 SQL 语句,如下代码所示

AbstractJdbcTemplate jdbcTemplate = new OrderJdbcTemplate();  
List<Order> orders = (List<Order>) jdbcTemplate.execute("select * from Order");

如果使用模板方法模式,我们在业务代码中需要定义各种实现类,我们需要创建和维护新类。

这也就是模板方法模式的弊端,使用了继承。我们知道写代码尽量使用接口而不是继承,也就是基于接口编程。

回调机制便是基于接口实现。

那么,我们将handleStatement 改为一个接口。

public interface StatementCallback {
    Object handleStatement(Statement statement) throws SQLException;  

}

那么原有的AbstractJdbcTemplate 需要修改如下:

public class CallbackJdbcTemplate {

 

    @Autowired

    private DataSource dataSource;

    

    public final Object execute(StatementCallback callback){  

        Connection connection = null;

        Statement statement = null;

        ResultSet resultSet = null;

        try {

            connection = dataSource.getConnection();

            statement = connection.createStatement();

            Object object = callback.handleStatement(statement);

            return object;

        } catch (SQLException e) {

            System.out.print(e);

        } finally {

            //省略异常处理

        }

        return null;

    }

}

上面的

 Object object = callback.handleStatement(statement);

使用了接口,这样把原来需要子类抽象的方法转嫁到了接口(StatementCallback )之上。
我们写代码的时候,就可以使用:

public Object queryOrder(final String sql)  {

 

        CallbackJdbcTemplate jdbcTemplate = new CallbackJdbcTemplate();

        return jdbcTemplate.execute(new StatementCallback() {
            public Object handleStatement(Statement statement) throws SQLException {
                ResultSet rs = statement.executeQuery(sql);
                List<Order> orders = new ArrayList<Order>();
                while (rs.next()) {
                    Order order = new Order(rs.getLong("id"), rs.getString("order_number"),
                            rs.getString("delivery_address"));

                    orders.add(order);
                }
                return orders;
            }
        });     
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值