行为型模式[模板方法模式]
模板设计模式定义:定义一个操作中的算法骨架,将步骤延迟到子类中。
模板设计模式是一种行为设计模式,一般是准备一个抽象类,将部分逻辑以具体方法或者具体的构造函数实现,然后声明一些抽象方法,这样可以强制子类实现剩余的逻辑。不同的子类以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板设计模式能达成的功能。
适用于一些复杂操作进行步骤分割、抽取公共部分由抽象父类实现、将不同的部分在父类中定义抽象实现、而将具体实现过程由子类完成。对于整体步骤很固定,但是某些部分易变,可以将易变的部分抽取出来,供子类实现。
// 模板抽象类
public abstract class AbstractWangZhe {
public void skillsToIntroduce() {
System.out.println("欢迎来到王者荣耀,王者英雄介绍马上开始");
// 钩子调用方法
hero();
Q();
W();
if (Eskills()) {
E();
}
R();
finish();
}
protected abstract boolean Eskills();
protected void finish() {
System.out.println("英雄介绍到此为止,感谢观看装饰模式");
}
protected abstract void hero();
protected abstract void Q();
protected abstract void W();
protected void E() {
System.out.println("没有三技能");
}
protected abstract void R();
}
// 具体实现类
public class DaQiao extends AbstractWangZhe {
private boolean isEskills = true;
@Override
protected boolean Eskills() {
return this.isEskills;
}
@Override
protected void hero() {
System.out.println("大桥:非云非雾如烟如霞,珠光珠色,杂卉杂花");
}
@Override
protected void Q() {
System.out.println("一技能:鲤跃之潮");
}
@Override
protected void W() {
System.out.println("二技能:宿命之海");
}
protected void E() {
System.out.println("三技能:决断之桥");
}
@Override
protected void R() {
System.out.println("大招技能:漩涡之门");
}
}
// 模板具体实现类
public class DiaoChan extends AbstractWangZhe {
private boolean isEskills = false;
@Override
protected boolean Eskills() {
return this.isEskills;
}
@Override
protected void hero() {
System.out.println("貂蝉:想欣赏,妾身的舞姿吗?");
}
@Override
protected void Q() {
System.out.println("一技能:落*红雨");
}
@Override
protected void W() {
System.out.println("二技能:缘*心结");
}
@Override
protected void R() {
System.out.println("大招技能:绽*风华");
}
}
public class Test {
public static void main(String[] args) {
AbstractWangZhe daqiao = new DaQiao();
daqiao.skillsToIntroduce();
System.out.println();
AbstractWangZhe diaoChan = new DiaoChan();
diaoChan.skillsToIntroduce();
}
}
抽象类和接口:
• 接口是一种特殊的抽象类,所有接口中的属性自动是常量,也就是public final static的,而所有接口中的方法必须是抽象的。
• 抽象类,简单点说是用abstract修饰的类。这里要特别注意的是抽象类和抽象方法的关系,记住两句话:抽象类不一定包含抽象方法;有抽象方法的类一定是抽象类。
• 抽象类和接口相比较,最大的特点就在于抽象类中是可以有具体的实现方法的,而接口中所有的方法都是没有具体的实现的。
• 通常在“既要约束子类的行为,又要为子类提供公共功能”的时候使用抽象类。
变与不变:
• 程序设计的一个很重要的思考点就是“变与不变”,也就是分析程序中哪些功能是可变的,哪些功能是不变的,然后把不变的部分抽象出来,进行公共的实现,把变化的部分分离出去,用接口来封装隔离,或者是用抽象类来约束子类行为。
• 模板方法模式很好地体现了这一点。模板类实现的就是不变的方法和算法的骨架,而需要变化的地方,都通过抽象方法,把具体实现延迟到子类中了,而且还通过父类的定义来约束了子类的行为,从而使系统能有更好的复用性和扩展性。
使用模板方法模式的优点:
• 模板方法模式是一种实现代码复用的很好的手段。通过把子类的公共功能提炼和抽取,把公共部分放到模板中去实现。
使用模板方法模式的缺点:
• 模板方法模式最基本的功能就是通过模板的制定,把算法骨架完全固定下来。事实上模板和子类是非常耦合的,如果要对模板中的算法骨架进行变更,可能就会要求所有相关的子类进行相应的变化。所以抽象算法骨架的时候要特别小心,尽量确保是不会变化的部分才放到模板中。
源码中的模板设计模式介绍
JdbcTemplate // 类当中的模板设计模式
private <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action, boolean closeResources) throws DataAccessException {
......
// 具体实现的模板过程
Connection con = DataSourceUtils.getConnection(this.obtainDataSource());
PreparedStatement ps = null;
Object var14;
try {
// 根据传进来的PreparedStatementCreator具体实现类执行步骤,做到钩子函数调用
ps = psc.createPreparedStatement(con);
// JdbcTemplate 原有的方法调用
this.applyStatementSettings(ps);
T result = action.doInPreparedStatement(ps);
this.handleWarnings((Statement)ps);
var14 = result;
} catch (SQLException var11) {
if (psc instanceof ParameterDisposer) {
((ParameterDisposer)psc).cleanupParameters();
}
String sql = getSql(psc);
psc = null;
JdbcUtils.closeStatement(ps);
ps = null;
DataSourceUtils.releaseConnection(con, this.getDataSource());
con = null;
throw this.translateException("PreparedStatementCallback", sql, var11);
} finally {
if (closeResources) {
if (psc instanceof ParameterDisposer) {
((ParameterDisposer)psc).cleanupParameters();
}
JdbcUtils.closeStatement(ps);
DataSourceUtils.releaseConnection(con, this.getDataSource());
}
}
return var14;
}
JDK原生的模板模式
abstractList // 抽象模板类中的get方法就是让子类实现钩子方法
abstract public E get(int index);// get方法
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i); // 如这个就是abstractList调用子类继承父类重写抽象方法后的钩子函数
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}