1、什么是模板模式?
模板方法模式(Template Method Pattern):定义一个操作中的算法的框架, 而将一些步骤延迟到子类中。 使得子类可以不改
变一个算法的结构即可重定义该算法的某些特定步骤。
说人话:父类模板方法定义不变的流程,子类重写流程中的方法。
2、模板模式定义
①、AbstractClass 抽象模板
一、基本方法
上面的 baseOperation() 或者 customOperation() 方法,也叫基本操作,是由子类实现的方法,并且在模板方法中被调用。
二、模板方法
上面的 templateMethod() 方法,可以有一个或者几个,实现对基本方法的调度,完成固定的逻辑。
②、ConcreteClass 具体模板
实现父类定义的一个或多个抽象方法,也就是父类定义的基本方法在子类中得以实现。
3、模板模式通用代码
public abstract class AbstractClass {
// 共同的且繁琐的操作
private void baseOperation() {
// do something
}
// 由子类定制的操作
protected abstract void customOperation();
// 模板方法定义的框架
public final void templateMethod() {
/**
* 调用基本方法,完成固定逻辑
*/
baseOperation();
customOperation();
}
}
public class ConcreteClass1 extends AbstractClass{
@Override
protected void customOperation() {
// 具体模板1 业务逻辑
System.out.println("具体模板1:customOperation()");
}
}
public class ConcreteClass2 extends AbstractClass{
@Override
protected void customOperation() {
// 具体模板2 业务逻辑
System.out.println("具体模板2:customOperation()");
}
}
测试:
public class TemplateClient {
public static void main(String[] args) {
AbstractClass abstractClass1 = new ConcreteClass1();
AbstractClass abstractClass2 = new ConcreteClass2();
applyTemplate(abstractClass1);
applyTemplate(abstractClass2);
}
public static void applyTemplate(AbstractClass abstractClass){
abstractClass.templateMethod();
}
}
4、模板模式优点
①、封装不变部分, 扩展可变部分
把认为是不变部分的算法封装到父类实现, 而可变部分的则可以通过继承来继续扩展。
②、提取公共部分代码, 便于维护
③、行为由父类控制, 子类实现
基本方法是由子类实现的, 因此子类可以通过扩展的方式增加相应的功能, 符合开闭原则。
5、模板模式缺点
①、子类执行的结果影响了父类的结果,这和我们平时设计习惯颠倒了,在复杂项目中,会带来阅读上的难度。
②、可能引起子类泛滥和为了继承而继承的问题
6、回调
为了解决模板模式的缺点,我们可以利用回调函数代替子类继承。
public interface Callback {
void customOperation();
}
public class SubCallback implements Callback{
@Override
public void customOperation() {
System.out.println("SubCallback customOperation");
}
}
/**
* 模板类
* 声明为 final,无法被继承
*/
public final class Template {
private void baseOperation(){
System.out.println("模板类公共操作");
}
public void templateMethod(Callback callback){
baseOperation();
callback.customOperation();
}
}
测试:
public class TemplateClient {
public static void main(String[] args) {
Template template = new Template();
applyTemplate(template);
}
public static void applyTemplate(Template template){
Callback callback = new SubCallback();
template.templateMethod(callback);
}
}
Template是一个稳定的final类,无法被继承,不存在子类行为影响父类结果的问题,而Callback是一个接口,为了继承而继承的问题消失了。