五、模板方法设计模式及在Spring中的应用

  如果字面理解比较抽象的话,那以生活中简单的行为为例:天热了,到了晚上妈妈都要将今天没有吃完的饭菜放入冰箱。将饭菜放入冰箱就是一个典型的模板设计:1、将冰箱门打开;2将饭菜放入冰箱;3、关闭冰箱。类推,任何需要放入冰箱的事物都需按如上的顺序进行操作,比如西瓜、面膜等。

  敲重点:不变的是顺序;变化的可以是放入冰箱的事物,也可以是开闭冰箱、放入冰箱使用的工具不同(之前用手,后来用脚~~举例而已)

  在软件设计的应用中怎么体现呢?上该设计模式的UML图,如下(借图改进):

                

   这里设计模板方法设计模式结构的一些具体术语:

    (1) 抽象类(Abstract Class):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。这些方法的定义如下:

      ① 模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。

      ② 基本方法:是整个算法中的一个步骤,包含以下几种类型:
        抽象方法:在抽象类中申明,由具体子类实现。
        具体方法:在抽象类中已经实现,在具体子类中可以继承或重写它。
        钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。

    (2) 具体子类(Concrete Class):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤。

  对于钩子方法的存在可能不太理解。模板方法模式中模板方法定义了行为的顺序,也就是程序的执行流程。在实际生产业务需求中这个执行流程应该是可干预的,怎么解决呢?那就需要通过钩子方法使得控制行为流程更加灵活。比如上面UML图中的钩子方法isSleep()。

  Spring容器中Bean的实例化注入就使用了模板方法模式,具体体现为模板方法:refresh()。具体分析如下:

  模板方法模式,那么首先找到模板方法。先上两张UML图:

              

                 

   两图简化合并后,如下:

                  

   上图与模板方法模式结构类似,那么类似就是模板方法设计模式么?得有模板方法才是。那看能不能找到模板方法:跟踪调试如下代码

                  

   调用构造函数如下,整个识别、实例化、注入bean的工作均完成:

                  

   继续跟踪发现,refresh()就是模板方法:提取方法中注释截图如下

                

    为什么refresh要按这个流程执行,可以通过其父类接口ConfigurableApplicationContext该方法声明的注释得到答案:

                

   refresh中的方法均为protected,在其子类中这些方法本身没有显示的改变,但是方法内调用的方法却在子类中有变化。以refreshBeanFactory()为例,在模板方法的第二部obtainFreshBeanFactory()中用到了,但是注解配置版与XML配置版获取的行为方式就是差别处理的,通过跟踪调试验证,如下图:

  注解配置版:

                 

                  

   XML配置版:

                  

                  

   注意以上两个具体方法前都是用了关键字 final。

  

posted on 2021-06-23 16:33  池塘里洗澡的鸭子  阅读(602)  评论(0编辑  收藏  举报