看了模板方法设计模式后,我理解它的作用相当于是:
抽象父类设计好了一些功能模板,然后子类去继承并实现这些具体功能。
这个过程就是,首先要做个抽象类,然后这个抽象类里面有一个功能方法调用了n个内部的抽象方法,我们都知道抽象方法类似于一个插槽,是给子类去重写实现的,例子如下:
public abstract class Car{ //车
public void drive(){
beforeDrive();
System.out.println("车跑起来了..");
stopCar();
}
public abstract void beforeDrive();
public abstract void stopCar();
}
这里面定义了一个Car抽象父类,有个drive的功能方法,在这drive方法里面有自己的功能逻辑如打印信息,也有调用了内部抽象方法beforeDrive和stopCar。子类要是想调用父类的drive方法,那就要重写beforeDrive和stopCar方法。
public class ManualCar extends Car{ //手动挡的车
@Override
public void beforeDrive() {
System.out.println("踩离合,挂一挡,踩油门");
}
@Override
public void stopCar() {
System.out.println("刹车,用力拉手刹");
}
}
public class AutomaticCar extends Car{ //自动挡的车
@Override
public void beforeDrive() {
System.out.println("踩刹车,挂D挡,踩油门");
}
@Override
public void stopCar() {
System.out.println("刹车,按电子手刹");
}
}
这就是一个模板方法模式的利用了,至于你beforeDrive(驾驶之前)和stopCar(刹车)要做些什么,按照子类实现来决定。
但这就完了嘛?事由是这样的,最近我在看一本讲Spring源码的书籍,在DefaultBeanDefinitionDocumentReader这个类的doRegisterBeanDefinitions方法,里面有一段是这样写的
protected void doRegisterBeanDefinitions(Element root) {
//省略前面的代码...
this.preProcessXml(root);
this.parseBeanDefinitions(root, this.delegate);
this.postProcessXml(root);
this.delegate = parent;
}
//doRegisterBeanDefinitions方法中引用到的两个方法
protected void preProcessXml(Element root) {//实际里面是空的 }
protected void postProcessXml(Element root) {//实际里面是空的 }
对于preProcessXml和postProcessXml这俩方法,作者说道这里面都是一个空的方法体,Spring就是借鉴了模板方法的思想去做的,作用是让子类在继承DefaultBeanDefinitionDocumentReader这个类时,只需要重写preProcessXml和postProcessXml这俩方法,然后子类调用doRegisterBeanDefinitions方法时,就可以在一个功能(parseBeanDefinitions方法)做一些前置操作和后置操作了。
我当时的疑惑就是,咦?为什么这个不是一个抽象方法抽象类,而是一个具体的类?居然还能这么写。后面问了下大佬,大佬解决了我的疑惑并纠正了我的想法 。
大佬的原话:“spring自己是要生成对象的,假如说它把那个类定义成抽象的,那它怎么生成对象?模板只要能继承就可以实现,具体类和抽象类都可以继承,并不一定非要抽象类”
后面我想了想,对呀,spring里面可能要把某些类做成对象,假如DefaultBeanDefinitionDocumentReader做成抽象类,那咋还能生成对象呢?感觉spring就是保持这个类是具体类,然后又能使用模板方法模式,依然能通过子类去继承这个类,再重写父类方法,也可以达到目的,于是就这样设计了。