设计模式-模板方法模式
当我们知道一个业务流程或算法的关键步骤,并且也确定了步骤的执行顺序,但是某些步骤的具体实现还不能确定或者有多个方案。这时候就可以利用模板方法设计模式,将某些具体实现还不能确定或者有多个方案的方法,封装为一个抽象方法,子类通过继承父类来实现不同步骤的具体实现。整体的工作流程却由父类进行控制。
举例一
我们来举个例子,我们要创建一个工作流程的类,基本的步骤是上班打卡,执行具体的工作内容,然后下班。但是不同的人工作内容是不同的,但是都会执行上班班和下班的步骤,我们可以把具体执行的工作内容封装为一个抽象方法,交给子类进行实现。来看看代码:
public abstract class AbstractWorkProcess {
public void work(){
//打卡
System.out.println("打卡成功");
jobContent();
//下班
System.out.println("下班");
}
// 具体的工作内容
public abstract void jobContent();
}
程序员子类
public class ProgrammerWork extends AbstractWorkProcess{
@Override
public void jobContent() {
System.out.println("敲代码");
}
}
老板子类
public class BossWork extends AbstractWorkProcess{
@Override
public void jobContent() {
System.out.println("喝茶");
}
}
测试类
public class TestTemplate {
public static void main(String[] args) {
// AbstractWorkProcess workProcess = new ProgrammerWork();
AbstractWorkProcess workProcess = new BossWork();
workProcess.work();
}
}
当我们实例化不同的子类的时候,具体的工作内容改变,但是总体的流程是不会变的。
打印结果:
打卡成功
喝茶
下班
举例二
还有一种场景,在Spring后处理器的应用中就有用到模板方法设计模式,在bean的生命周期中,可能会应用不同的后处理器,但是这些后处理器都不是固定的。我们来看示例代码。
public class MyBeanFactoryTest {
public static void main(String[] args) {
MyBeanFactory myBeanFactory = new MyBeanFactory();
myBeanFactory.getBean();
}
static class MyBeanFactory{
public void getBean(){
Object bean = new Object();
System.out.println("构造:"+bean);
System.out.println("依赖注入:"+bean);
System.out.println("初始化:"+bean);
}
}
}
MyBeanFactory的getBean方法,示例了获取bean的一个流程,分为构造,依赖注入,初始化,当我们需要在依赖注入这个阶段新增一个功能,比如解析@Autowired注解。如果不使用模板方法设计模式,我们可能会这样写:
public void getBean(){
Object bean = new Object();
System.out.println("构造:"+bean);
System.out.println("依赖注入:"+bean);
System.out.println("解析@Autowired");
System.out.println("初始化:"+bean);
}
如果以后又有新增的功能比如要解析@Resource,我们再去改之前的代码吗,或者根本不需要去解析@Autowired注解呢?这样把代码写死了,对以后的扩展,以及使用的灵活性都造成了影响。
通过前面对模板方法模式的介绍,我们可以想到,可以把扩展功能增强的部分抽离出来,交给子类来实现,Spring采用的另外一种方式,我们来模拟一下:
public class MyBeanFactoryTest {
public static void main(String[] args) {
MyBeanFactory myBeanFactory = new MyBeanFactory();
myBeanFactory.addBeanPostProcessor(new AutowiredBeanPostProcessor());
myBeanFactory.getBean();
}
static class MyBeanFactory{
private final List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
public void getBean(){
Object bean = new Object();
System.out.println("构造:"+bean);
System.out.println("依赖注入:"+bean);
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
beanPostProcessor.inject();
}
System.out.println("初始化:"+bean);
}
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor){
beanPostProcessorList.add(beanPostProcessor);
}
}
static interface BeanPostProcessor{
void inject();
}
static class AutowiredBeanPostProcessor implements BeanPostProcessor{
@Override
public void inject() {
System.out.println("解析@Autowired");
}
}
}
Spring的做法是将后处理器类抽象出来,称为一个接口,然后添加进后处理器集合中进行循环调用,这样就可以新增、减少、排序后处理器,比如要增加@Resource的处理,只需要再实现一个ResourceBeanPostProcessor,然后添加到后处理器集合中就行了。