(二十三)模板方法模式

一、概念

在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤

二、基本内容

  • 1、父类抽象出子类共有的方法,并自己实现他
  • 2、子类实现各自不同的业务
  • 3、父类实现的方法按照一定逻辑调用抽象方法
  • 4、为了防止子类重写父类的方法,父类定义为final方法

三、在父类中增加钩子

  • (1)可以让子类实现算法中可选的部分
  • (2)在钩子对于子类的实现并不重要的时候,子类可以对此钩子置之不理
  • (3)可以让子类能够有机会对模板方法中某些即将发生的步骤做出反应

四、案例

(1)定义抽象父类

public abstract class AbstractClass {
    /**
     * 模板方法,给出了逻辑的骨架,而逻辑的组成是一些相应的抽象操作
     * 声明为final,防止子类重写
     */
    final void templateMethod(){
        primitiveOperation1();
        primitiveOperation2();
        concreteOperation();
    }
    /**
     * 抽象行为放到子类实现
     */
    abstract void primitiveOperation1();
    abstract void primitiveOperation2();

    /**
     * 钩子方法,子类可通过需求选择是否进行重写
     */
    void concreteOperation(){

    }
}

(2) 定义子类

public class ConcreteClassA extends AbstractClass {

    @Override
    void primitiveOperation1() {
        System.out.println("实现A中的操作1");
    }

    @Override
    void primitiveOperation2() {
        System.out.println("实现A中的操作2");
    }

    @Override
    void concreteOperation() {
        System.out.println("钩子方法,A中可实现自己的内容");
    }
}


public class ConcreteClassB extends AbstractClass {

    @Override
    void primitiveOperation1() {
        System.out.println("实现B中的操作1");
    }

    @Override
    void primitiveOperation2() {
        System.out.println("实现B中的操作2");
    }

    @Override
    void concreteOperation() {
        System.out.println("钩子方法,B中可实现自己的内容");
    }
}

(3)测试调用

public static void main(String[] args) {
    AbstractClass a = new ConcreteClassA();
    a.templateMethod();

    AbstractClass b = new ConcreteClassB();
    b.templateMethod();

}

五、类图

在这里插入图片描述

六、应用场景

  • InputStream

其中的read()方法,由子类实现
被read(byte b[], int off, int len)模板方法调用

abstract int read()
  • JUC中的AQS

acquire相当于模板方法,tryAcquire相当于基本方法

public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}
  • JdbcTemplate

execute 相当于模板方法,doInStatement()相当于基本方法,由子类实现

@Override
	@Nullable
	public <T> T execute(StatementCallback<T> action) throws DataAccessException {
		Assert.notNull(action, "Callback object must not be null");

		Connection con = DataSourceUtils.getConnection(obtainDataSource());
		Statement stmt = null;
		try {
			stmt = con.createStatement();
			applyStatementSettings(stmt);
			T result = action.doInStatement(stmt);
			handleWarnings(stmt);
			return result;
		}
		catch (SQLException ex) {
			// Release Connection early, to avoid potential connection pool deadlock
			// in the case when the exception translator hasn't been initialized yet.
			String sql = getSql(action);
			JdbcUtils.closeStatement(stmt);
			stmt = null;
			DataSourceUtils.releaseConnection(con, getDataSource());
			con = null;
			throw translateException("StatementCallback", sql, ex);
		}
		finally {
			JdbcUtils.closeStatement(stmt);
			DataSourceUtils.releaseConnection(con, getDataSource());
		}
	}

七、和策略模式比较

  • 策略模式:
  1. 使用组合方式,让客户选择算法实现
  2. 定义不同的算法,可以互换
  • 模板方法:
  1. 使用继承方式,子类自己实现算法
  2. 定义了算法步骤,具体的实现延迟到子类
发布了18 篇原创文章 · 获赞 0 · 访问量 278
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 游动-白 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览