模板模式主要是用来解决 复用 和 扩展 两个问题,常用于框架的开发中。
定义:模板方法模式在一个方法中定义一个算法骨架(指的是广义上的“业务逻辑”),并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。
一、模板模式的基本实现方式:
1、模板方法 templateMethod() 定义成 final,是为了避免子类重写。将业务逻辑中不变的部分抽象到模板方法中来。
2、模板方法中的具体处理逻辑 method1 和 method2 定义成 abstract,是为了强迫子类重写。将子类间可自定义的部分,放在method中实现。从而满足对于框架的扩展
public abstract class AbstractClass {
public final void templateMethod() {
//...
method1();
//...
method2();
//...
}
protected abstract void method1();
protected abstract void method2();
}
public class ConcreteClass1 extends AbstractClass {
@Override
protected void method1() {
//...
}
@Override
protected void method2() {
//...
}
}
public class ConcreteClass2 extends AbstractClass {
@Override
protected void method1() {
//...
}
@Override
protected void method2() {
//...
}
}
AbstractClass demo = ConcreteClass1();
demo.templateMethod();
二、模板模式与CallBack函数有什么区别和联系:
1、回调的原理
回调CallBack的作用:与模板模式相同,复用和扩展;
回调的原理:相对于普通的函数调用来说,回调是一种双向调用关系。A 类事先注册某个函数 F 到 B 类,A 类在调用 B 类的 P 函数的时候,B 类反过来调用 A 类注册给它的 F 函数。这里的 F 函数就是“回调函数”。A 调用 B,B 反过来又调用 A,这种调用机制就叫作“回调”。
除了回调函数之外,BClass 类的 process() 函数中的逻辑都可以复用。如果 ICallback、BClass 类是框架代码,AClass 是使用框架的客户端代码,我们可以通过 ICallback 定制 process() 函数,也就是说,框架因此具有了扩展的能力。
回调的代码实现:
public interface ICallback {
void methodToCallback();
}
public class BClass {
public void process(ICallback callback) {
//...
callback.methodToCallback();
//...
}
}
public class AClass {
public static void main(String[] args) {
BClass b = new BClass();
b.process(new ICallback() { //回调对象
@Override
public void methodToCallback() {
System.out.println("Call back me.");
}
});
}
}
2、模板模式 和 回调的区别
代码实现方面二者的区别:
回调基于组合关系来实现,把一个对象传递给另一个对象,是一种对象之间的关系;
模板模式基于继承关系来实现,子类重写父类的抽象方法,是一种类之间的关系。
从设计模式上来讲,组合优于继承。实际上,这里也不例外。在代码实现上,回调相对于模板模式会更加灵活,主要体现在下面几点。
- 像 Java 这种只支持单继承的语言,基于模板模式编写的子类,已经继承了一个父类,不再具有继承的能力。
- 回调可以使用 匿名类 来创建回调对象,可以不用事先定义类;而模板模式针对不同的实现都要定义不同的子类。
- 如果某个类中定义了多个模板方法,每个方法都有对应的抽象方法,那即便我们只用到其中的一个模板方法,子类也必须实现所有的抽象方法。而回调就更加灵活,我们只需要往用到的模板方法中注入回调对象即可。