13、设计模式之模板模式(Template)

一、什么是模板模式

模板模式是一种基于继承实现的设计模式,它是行为型的模式。

主要思想是将定义的算法抽象成一组步骤,在抽象类种定义算法的骨架,把具体的操作留给子类来实现。

通俗地说,模板模式就是将某一行为制定一个框架,然后子类填充细节。比如说做菜,流程通常就是洗菜、切菜、炒菜等步骤,那么这个流程就可以看作是一个模板,而具体做什么菜由子类来实现。

二、角色组成

抽象类(Abstract):定义了算法骨架,包含一个或多个抽象方法,这些方法由子类来具体实现。抽象类中通常还包含一个模板方法,用来调用抽象方法和具体方法,控制算法的执行顺序;还可以定义钩子方法,用于在算法中进行条件控制。

具体类(Concrete Class):继承抽象类,实现抽象方法。

三、优缺点

优点:

提高代码复用性:将算法的骨架定义在父类中,子类只需要实现具体的细节部分,减少了代码的重复。

符合开闭原则:在模板模式种,由父类控制子类的执行,通过子类对父类进行扩展增加新的行为,符合"开闭原则"。

提高代码可维护性:模板模式定义了一套固定的模板,便于开发人员理解和修改,易于维护。

缺点:

部分子类可能无法灵活定制:由于模板模式制定的是一个固定的结构,所以某些子类可能无法适用,导致无法实现特定的需求或定制。

类的数量增加:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

四、应用场景

4.1 生活场景

写文章:假设我们要写一篇文章,其中包括标题、引言、正文和结论等部分。我们可以将文章的写作过程定义为一个模板,在抽象类中定义写作方法,如先写标题、再写引言、接着写正文,最后写结论。具体类就是每篇文章的实现类,它们可以根据主题和内容的不同来实现对应的部分。这样,每个具体文章类只需要关注自己特定的内容,而写作的步骤则由模板来控制

学习流程:比如学习某门课程的流程,在学习过程中有一些共同的步骤,比如预习、上课、复习做练习等。我们可以定义一个抽象类StudyCourse,在其中定义学习的方法。具体类就是每门具体课程的实现类,它们根据课程内容和学习方式来实现抽象类中的方法。模板方法则是定义在抽象类中的一组方法,用于规定学习的整体流程和一些基本规则。

4.2 java场景

JdbcTemplate:JdbcTemplate提供了一系列的模板方法,如execute、query、update等。开发者可以通过继承JdbcTemplate并实现相应的抽象方法来完成数据库操作的具体实现。

HttpServlet:HttpServlet类是一个抽象类,提供了handleRequest、doGet、doPost等模板方法,用于处理HTTP请求。Servlet开发者可以继承HttpServlet并实现这些方法来处理具体的请求,从而完成一个特定的Servlet实现。

Servlet过滤器:Java Servlet

API中提供了过滤器(Filter)接口,用于对Servlet请求进行拦截和处理。该接口中定义了一个doFilter()方法,该方法是一个模板方法,由子类实现具体的请求拦截和处理方式。

五、代码实现

下面以订外卖为例,解释一下模板模式。假设订外卖的过程包含三个步骤:选择外卖、支付、取外卖、是否打赏,我们可以定义一个OderFood的抽象类,那么选择外卖就可以是抽象方法,需要子类取实现它,支付和取外卖可以定义为具体方法,另外是否打赏为钩子方法,子类可以决定是否对算法的不同进行挂钩,还需要定义一个模板方法,用以控制流程;不同的商家,如KFC、星巴克就是具体类。

5.0 UML类图

5.1 OrderFood------抽象类(Abstract)

java 复制代码
/**
 * 
 * 1.抽象类(Abstract Class):点外卖
 * 包含选择外卖、支付、取外卖三个方法,
 * 其中选择外卖为抽象方法,需要子类实现
 * 支付、取外卖为具体方法
 * 另外是否打赏为钩子方法,子类可以决定是否对算法的不同进行挂钩
 */
public abstract class OrderFood {
 
    //模板方法
    public void order(){
        selectFood();
        pay();
        getFood();
    }
    //选择外卖   抽象方法 由子类实现具体细节
    public abstract void selectFood();
    //是否打赏   钩子方法 可以重写来做条件控制
    public boolean isGiveAward(){
        return false;
    }
    //-------具体方法----------
    public void pay(){
        System.out.println("支付成功,外卖小哥正在快马加鞭~~");
    }
 
    //取外卖
    public void getFood(){
        System.out.println("取到外卖");
        if (isGiveAward()){
            System.out.println("打赏外卖小哥");
        }
    }
}

5.2 具体类(Concrete Class)

java 复制代码
/**
 * 
 * 具体类(Concrete Class):星巴克
 */
public class Starbucks extends OrderFood{
 
    //实现父类方法
    @Override
    public void selectFood() {
        System.out.println("一杯抹茶拿铁");
    }
 
    //重写钩子方法,打赏外卖小哥
    @Override
    public boolean isGiveAward(){
        return true;
    }
}
/**
 * 
 * 具体类(Concrete Class):KFC
 */
public class KFC extends OrderFood{
    @Override
    public void selectFood() {
        System.out.println("一份汉堡炸鸡四件套");
    }
}

5.3 testTemplate

java 复制代码
/**
 * 
 * 模板模式测试类
 */
@SpringBootTest
public class TestTemplate {
 
    @Test
    void testTemplate(){
        //星巴克(重写了钩子方法,打赏外卖小哥)
        OrderFood orderFood=new Starbucks();
        orderFood.order();
        System.out.println("--------KFC------------");
        //KFC
        OrderFood orderFood1=new KFC();
        orderFood1.order();
    }
}

六、总结

我们可以把模板看作是一个公共的蓝本,而子类就像是根据这个蓝本来实现自己独特的需求。所以当我们在开发中遇到一些情况,比如多个类共享一些相同的操作,或者说想要控制子类扩展某个算法的一部分功能时,就可以考虑模板模式了。另外,还有以下几个适用场景以做参考:

子类需要扩展算法的部分功能:当需要控制子类对算法的某些步骤进行扩展或修改,同时保持算法骨架不变时,可以使用模板模式。

实现多个算法的不同细节:当需要在不同的场景下使用相同的算法,但是细节实现不同,可以使用模板模式。

需要统一流程的业务:在一些对流程敏感的业务中,例如订餐、下单等,使用模板方法模式可以统一流程,使代码更加简洁和易维护。并且在统一流程的同时,也能保证业务的正确性。

注意事项: 为防止恶意操作,一般模板方法都加上 final 关键词。

相关推荐
程序猿小柒8 分钟前
【LeetCode每日一题】LeetCode 345.反转字符串中的元音字母
算法·leetcode
ha204289419410 分钟前
认识数据结构之——排序
数据结构·算法·排序算法
小金的学习笔记16 分钟前
隐藏指定文件/文件夹和自动提示功能消失解决方案
java·idea
Q_192849990617 分钟前
基于Spring Boot的个性化推荐外卖点餐系统
java·spring boot·后端
会说法语的猪30 分钟前
IDEA使用Alt + Enter快捷键自动接受返回值一直有final修饰的问题处理
java·ide·intellij-idea
十年一梦实验室33 分钟前
【C++】sophus : rxso3.hpp 实现了 3D 空间中的旋转和缩放操作的 RxSO3 类 (二十一)
开发语言·c++·人工智能·算法·3d
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ39 分钟前
MyBatis执行完sql后,返回的数值代表的意思
java·开发语言
西岸行者1 小时前
捋一捋相关性运算,以及DTD和NLP中的应用
人工智能·算法·自然语言处理·信号处理
No0d1es1 小时前
GESP CCF C++六级编程等级考试认证真题 2024年12月
开发语言·c++·算法·青少年编程·gesp·ccf·六级
思忖小下1 小时前
梳理你的思路(从OOP到架构设计)_设计模式Composite模式
设计模式·组合模式·eit