设计模式之模板方法模式

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

设计模式之模板方法模式


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


一、概念理解

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

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


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

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


二、案例实现

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

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


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


假设创建对象有两种方式,一种是基于注解,一种是基于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()方法的执行大流程注释。

微信图片_20221014203635.png

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


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


三、总结

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


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

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


相关文章
|
6月前
|
设计模式 算法
二十三种设计模式全面解析-深入解析模板方法模式的奇妙世界
二十三种设计模式全面解析-深入解析模板方法模式的奇妙世界
|
设计模式 存储 算法
行为型设计模式02-模板方法模式
行为型设计模式02-模板方法模式
50 0
|
设计模式 算法
设计模式9 - 模板方法模式【Template Method Pattern】
设计模式9 - 模板方法模式【Template Method Pattern】
37 0
|
设计模式 算法 Java
设计模式~模板方法模式(Template method)-10
目录 (1)优点: (2)缺点: (3)使用场景: (4)注意事项: (5)应用实例: (6)Servlet Api &
57 0
|
2月前
|
设计模式 算法 Java
Java设计模式-模板方法模式(14)
Java设计模式-模板方法模式(14)
|
4月前
|
设计模式 JavaScript 算法
js设计模式【详解】—— 模板方法模式
js设计模式【详解】—— 模板方法模式
48 6
|
5月前
|
设计模式 算法 关系型数据库
设计模式第七讲-外观模式、适配器模式、模板方法模式详解
系统要求所有的数据库帮助类必须实现ISqlHelp接口,面向该接口编程,如SQLServerHelp类。 此时第三方提供了一个新的MySql的帮助类(假设是dll,不能修改),它的编程规范和ISqlHelp不兼容,这个时候就需要引入适配器类,使二者能相互兼容。
170 0
|
6月前
|
设计模式 算法 Java
Java 设计模式:深入模板方法模式的原理与应用
【4月更文挑战第27天】模板方法模式是一种行为设计模式,主要用于定义一个操作中的算法的框架,允许子类在不改变算法结构的情况下重定义算法的某些特定步骤。
60 1
|
6月前
|
设计模式 Go
[设计模式 Go实现] 行为型~模板方法模式
[设计模式 Go实现] 行为型~模板方法模式
|
6月前
|
设计模式 算法 Java
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式