zoukankan      html  css  js  c++  java
  • 设计模式——模板方法模式

    一、定义与简单实现

    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) { }

    总结:模板方法模式特点:

    在一个方法中定义一个算法的骨架(执行顺序),而将一些步骤延迟到子类中,模板方法还可以使得子类可以在不改变算法结构的情况下。重新定义算法中的某些步骤(钩子)。

    强调的是方法执行顺序,还有延迟到子类实现。

  • 相关阅读:
    普通的一个python脚本,hadoop进军的准备
    Python之数据类型讲解
    开始博客的理由
    【微机原理及应用】程序的分类
    【jvm】jvm学习第二篇。jvm运行机制
    【jvm】jvm学习第一篇。初识jvm
    【it公司】it公司简介-项目流程-研发小技巧
    【感悟】20岁的人生不应该停止奋斗。----------------努力努力再努力
    【书籍学习】史上最全的Java进阶书籍推荐
    【职业规划】3年工作经验的程序员应该具备的技能
  • 原文地址:https://www.cnblogs.com/wqff-biubiu/p/12691879.html
Copyright © 2011-2022 走看看