设计模式——模板方法模式
一、定义与简单实现
1、定义
- 模板方法是一个定义在父类中的方法,
- 在模板方法中会顺序调用多个定义在父类中的其他方法,而这些方法有可能只是抽象方法,
- 模板方法保证了抽象方法的执行顺序,这些抽象方法由子类实现,并且子类不允许覆写模板方法。
2、UML类图
模板方法模式与工厂方法模式的UML类图实现都是父类定义抽象方法,然后将具体实现延迟到子类,但还是有区别的
- 模板方法模式是行为型设计模式,关注的是对象之间交流,可以是一个没有返回值的方法。
- 工厂方法模式是创建型设计模式,关注的是对象的创建,必须返回一个创建好的对象。
模板方法模式中的设计原则:
- 封装变化(抽象方法)
- 依赖抽象,不依赖具体类
- 对扩展开放,对修改关闭
3、简单代码实现
public interface TemplateService { void templateMethod(); } public abstract class AbstractTemplateService implements TemplateService { @Override public void templateMethod() { //模板方法中的钩子方法isDoSomething1,子类可以改变方法执行顺序 if(isDoSomething1()){ doSomething1(); } doSomething2(); doSomething3(); } protected boolean isDoSomething1(){ return true; } protected void doSomething1(){ System.out.println("something1 start"); } /** * 子类不必实现,可以是空方法 */ protected void doSomething2(){ } protected abstract void doSomething3(); } public class ATemplateServiceImp extends AbstractTemplateService { @Override protected void doSomething3() { System.out.println("I am A"); } } public class BTemplateServiceImp extends AbstractTemplateService { @Override protected boolean isDoSomething1() { return false; } @Override protected void doSomething2() { System.out.println("I am B"); } @Override protected void doSomething3() { //empty } } public class Main { public static void main(String[] args) { TemplateService template = new ATemplateServiceImp(); template.templateMethod(); template = new BTemplateServiceImp(); template.templateMethod(); } }
二、框架中的模板方法模式
模板方法在成熟的框架中用到的地方很多,最常见的就是SpringIOC容器的初始化
1、springIOC容器初始化
AbstractApplicationContext是一个抽象类,是SpringIOC容器类的超类。
它的refresh()方法就是一个模板方法,各种各样的springIOC容器都是根据这个模板方法初始化的。
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // ② IOC初始化前的装备(配置环境参数、创建监听器、事件容器) prepareRefresh(); // ③ 这里可以分为两类: // GenericApplicationContext: 仅仅是控制beanfactory不能重复refresh // AbstractRefreshableApplicationContext:允许重复refresh,销毁就beanfactory,创建新beanfactory并且重新扫描生成beanDefinitionMap容器。 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // ④ 设置beanfactory的一些属性(bean的类加载器、忽略接口、BeanPostProcessor、环境参数单例注册到beanfactory单例容器中) prepareBeanFactory(beanFactory); try { // ⑤空方法,留由子类实现。 //例如注册servlet相关的忽略接口、beanPostProcessor、各作用域生成bean的bean工厂 //注册servlet的一些单例(servletContext/servletConfig/contextparameters/contextAttributes)到beanfactory的单例容器中 postProcessBeanFactory(beanFactory); // ⑥beanFactoryPostProcessor排序并依次调用 // beanFactoryPostProcessor:beanfactory的后置处理器,可以理解为一个beanfactory的拦截器(实例化后需要执行的自定义操作) // 例如:beanfactory初始化完成后,修改忽略接口、甚至可以对特定的beandefinition做修改 invokeBeanFactoryPostProcessors(beanFactory); // ⑦BeanPostProcessors排序并依次注册到beanfactory的beanpostProcessor容器中 // beanPostProcessors:bean实例化的处理器,可以理解为一个bean的拦截器(实例化前+实例化后需要执行自定义操作) // 例如:bean单例化前,修改beandefinition的属性。 //实例化后DI, //拦截getbean()拦截返回一个代理类bean registerBeanPostProcessors(beanFactory); // ⑧初始化国际化文件,支持国际化 initMessageSource(); // ⑨初始化时间监听器并注册到beanfactory的单例容器中 initApplicationEventMulticaster(); // ⑩空方法,子类实现,初始化一些自定义bean并注册到beanfactory的单例容器中 // 例如:themeSource,支持主题切换 onRefresh(); // ⑪注册个中监听器到beanfactory指定容器中 registerListeners(); // ⑫实例化不需要延迟加载的所有单例类型的bean(scope = singleton) finishBeanFactoryInitialization(beanFactory); // ⑬容器初始化完成,触发各种事件监控,ApplicationListener.onApplicationEvent()的执行时机(dubbo注册就是在这里实现的) // 例如:beanfactory的生命周期监控 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // ⑭ 容器初始化失败,销毁所有已实例化的bean destroyBeans(); // ⑮ 设置active = false cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // ⑯ 清空公共的反射缓存 resetCommonCaches(); } } }
2、JDK的ThreadPoolExecutor
线程池ThreadPoolExecutor的工作线程执行时,拓展了一个执行前,执行后方法
final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { while (task != null || (task = getTask()) != null) { w.lock(); if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt(); try { beforeExecute(wt, task); Throwable thrown = null; try { task.run(); } catch (RuntimeException x) { thrown = x; throw x; } catch (Error x) { thrown = x; throw x; } catch (Throwable x) { thrown = x; throw new Error(x); } finally { afterExecute(task, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { processWorkerExit(w, completedAbruptly); } } protected void beforeExecute(Thread t, Runnable r) { } protected void afterExecute(Runnable r, Throwable t) { }
总结:模板方法模式特点:
在一个方法中定义一个算法的骨架(执行顺序),而将一些步骤延迟到子类中,模板方法还可以使得子类可以在不改变算法结构的情况下。重新定义算法中的某些步骤(钩子)。
强调的是方法执行顺序,还有延迟到子类实现。