• 设计模式之模板方法模式


    在我们实际开发中,如果一个方法极其复杂时,如果我们将所有的逻辑写在一个方法中,那维护起来就很困难,要替换某些步骤时都要重新写,这样代码的扩展性就很差,当遇到这种情况就要考虑今天的主角——模板方法模式。

    一、概念理解

    模板方法模式的概念很简单,在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

    既然概念叫“骨架”,那想当然的就是定义一个抽象类,这是模板方法模式的第一个角色——抽象模板角色,要有延迟子类实现骨架方法,这是模板方法的第二个角色——具体模板角色。

    抽象模板角色:定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤,定义并实现了一个模板方法。

    具体模板角色:实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。每一个抽象模板角色都可以有任意多个具体模板角色与之对应。

    二、案例实现

    在我们的业务开发中往往都需要很多对象、很多方法,对象间也大都存在依赖关系,如果我们手动创建、管理对象就是一件极其困难的事。

    如果我们使用工厂模式用于创建对象,使用一个容器用于管理对象,那么再使用起来就变得极其简单了。

    在“这个过程”中创建对象就是一个很复杂的算法,而且创建对象的方式往往也不是单一的,我们要考虑能替换算法,这时候就可以使用模板方法模式。

    假设创建对象有两种方式,一种是基于注解,一种是基于xml,我们就将该方法定义为一个模板方法,基于注解和基于xml让子类去实现。

    我们用refresh()方法代表这个复杂的过程,在这个过程中应该包括:

    ①开始工作前的预处理;

    ②创建管理对象的容器(模板方法,基于注解和基于XML交给子类实现);

    ③模板方法(交给子类,方便扩展);

    ④其他方法(容器刷新后、国际化、应用监听、发布事件,等等等一堆事)。

    我们基于模板方法模式我们实现简单的demo。

    抽象模板角色:

    我们在抽象模板角色中实现部分逻辑,而创建对象的容器obtainFreshBeanFactory()方法交给子类实现,onRefresh()空方法交给子类实现便于扩展。

    /**
     * 抽象模板角色
     * @author tcy
     * @Date 28-09-2022
     */
    public abstract class AbstractApplicationContext {
    
        /**
         * 案例中容器和对象的创建全过程
         */
        public void refresh(){
    
            this.prepareRefresh();
    
            this.obtainFreshBeanFactory();
    
            this.onRefresh();
        }
    
        protected void prepareRefresh(){
            System.out.println("我用于开始工作前的预处理...");
        }
    
        protected void obtainFreshBeanFactory(){
            System.out.println("我用于创建默认管理对象的容器...");
        }
    
        /**
         * 模板方法,子类去实现[springboot实现了他,感兴趣具体可以研究一下]
         */
        protected void onRefresh() {
        }
    
    
        protected void otherMethod(){
            System.out.println("容器刷新后、国际化、应用监听、发布事件,等等等,一堆事");
        }
    }
    

    具体模板角色-基于注解创建管理对象的容器

    /**
     * 具体模板角色-基于注解
     * @author tcy
     * @Date 28-09-2022
     */
    public class ApplicationContextAnnotation extends AbstractApplicationContext {
        @Override
        protected void obtainFreshBeanFactory() {
            System.out.println("这是基于注解的创建对象容器...");
        }
    }
    

    具体模板角色-基于xml创建管理对象的容器

    /**
     * 具体模板角色-基于xml
     * @author tcy
     * @Date 28-09-2022
     */
    public class ApplicationContextXml extends AbstractApplicationContext {
        @Override
        protected void obtainFreshBeanFactory() {
            System.out.println("这是xml的创建对象容器...");
        }
    }
    

    客户端-模拟容器启动过程:

    /**
     * 容器启动过程
     * @author tcy
     * @Date 28-09-2022
     */
    public class Client {
        public static void main(String[] args) {
    
    		//基于xml方式
            ApplicationContextXml applicationContextXml = new ApplicationContextXml();
            applicationContextXml.refresh();
    
    		//基于注解方式
            ApplicationContextAnnotation annotation=new ApplicationContextAnnotation();
            annotation.refresh();
    
        }
    }
    
    我用于开始工作前的预处理...
    这是xml的创建对象容器...
    容器刷新后、国际化、应用监听、发布事件,等等等,一堆事
    我用于开始工作前的预处理...
    这是基于注解的创建对象容器...
    容器刷新后、国际化、应用监听、发布事件,等等等,一堆事
    

    对Spring源码稍微有点了解的同学大概已经知道,我们案例实现的正是简易版的Spring的Refresh()方法,Refresh()方法是Spring最核心的方法,Spring良好的扩展性正是离不开模板方法模式的运用。下图为Spring核心Refresh()方法的执行大流程注释。

    image-20220929094055185

    在我们案例中的onRefresh()的空方法,实际中Springboot就是实现了这个空方法,onRefresh()方法调用了Tomcat的jar包启动,这也是Springboot不需要手动注入Tomcat的原因。

    相信通过这个案例的理解,大部分同学不仅能很好的理解模板方法模式,想必对Spring的启动过程也有了一个大概的了解。

    三、总结

    模板方法应用场景太普遍了,在实际开发中有多个子类共有的方法,并且逻辑相同,可以考虑使用模板方法模式。当面对重要、复杂的算法,也可以把核心算法设计为模板方法模式,相关细节则由各个子类实现。

    模板方法优点突出:封装不变部分,扩展可变部分;提取公共代码,便于维护;行为由父类控制,子类实现。

    模板方法的缺点很明显,当方法实现过多的时候,每一个不同的实现都需要一个子类来实现,这必然导致类的个数增加,使得系统变得更加庞大。

    个人独立开发的应用框架芒果管理系统后端,支持前后端代码生成、支持字段注解等实用开发功能已全部开源,感兴趣的同学可以点个star鼓励我一下。这是芒果管理系统前端

    设计模式的学习要成体系,推荐你看我往期发布的设计模式文章。

    一、设计模式概述

    二、设计模式之工厂方法和抽象工厂

    三、设计模式之单例和原型

    四、设计模式之建造者模式

    五、设计模式之代理模式

    六、设计模式之适配器模式

    七、设计模式之桥接模式

    八、设计模式之组合模式

    九、设计模式之装饰器模式

    十、设计模式之外观模式

    十一、外观模式之享元模式

    十二、设计模式之责任链模式

    十三、设计模式之命令模式

    十四、设计模式之解释器模式

    十五、设计模式之迭代器模式

    十六、设计模式之中介者模式

    十七、设计模式之备忘录模式

    十八、设计模式之观察者模式

    十九、设计模式之状态模式

    二十、设计模式之策略模式

  • 相关阅读:
    【工具篇】Unity翻书效果插件Book-Page Curl Pro教程
    【踩坑篇】代码中使用 Long 作为 Map的Key存在的问题
    “内鬼”作祟,国内知名游戏公司被黑
    淘宝官方订单 API 接口,获取购买到的商品订单详情
    【教程7】疯壳·ARM功能手机-BLE透传实验教程
    【前端】Vue+Element UI案例:通用后台管理系统-登陆不同用户显示不同菜单、动态添加路由
    java ssm基于B_S架构的互联网在线培训教育平台
    python字符串相关
    值得收藏的30道Python练手题(附详解)
    游戏编程模式 - 命令模式
  • 原文地址:https://www.cnblogs.com/tianClassmate/p/16740392.html