模板方法模式 (Template Method Pattern)

文章目录

      • 模板方法模式 (Template Method Pattern)
      • 原理
      • 优点
      • 缺点
      • 示例代码
        • 场景描述
        • 1. 定义抽象类
        • 2. 创建具体类
        • 3. 客户端代码
        • 输出结果
      • UML 类图
      • 钩子方法
      • 使用场景
      • 优化与扩展
      • 小结

模板方法模式 (Template Method Pattern)

模板方法模式是一种 行为型设计模式,它定义了一个操作的骨架,将具体的实现延迟到子类。通过模板方法模式,子类可以在不改变骨架的情况下重新定义某些步骤。


原理

  1. 核心思想
    • 在一个方法中定义算法的框架,将具体实现留给子类。
    • 提取公共逻辑到父类中,便于代码复用。
  2. 适用场景
    • 一些操作步骤是固定的,但某些步骤需要由子类定制。
    • 存在多个类有类似的行为,需要复用相同的逻辑。
  3. 参与角色
    • AbstractClass(抽象类):定义模板方法和抽象方法,模板方法给出逻辑骨架。
    • ConcreteClass(具体类):实现抽象方法,提供特定步骤的具体逻辑。

优点

  1. 代码复用:将通用逻辑提升到父类。
  2. 灵活扩展:子类可以灵活定制具体实现。
  3. 封装不变部分:将变化部分交由子类处理。

缺点

  1. 增加复杂性:引入了继承关系。
  2. 子类数量增加:不同实现需要创建多个子类。

示例代码

场景描述

以咖啡和茶的制作过程为例。两者的制作过程大致相同,但某些步骤不同。


1. 定义抽象类
// 抽象类
public abstract class Beverage {
    // 模板方法,定义制作流程
    public final void prepareBeverage() {
        boilWater();
        brew();
        pourInCup();
        if (addCondimentsHook()) { // 使用钩子方法
            addCondiments();
        }
    }

    // 通用方法:烧水
    private void boilWater() {
        System.out.println("Boiling water...");
    }

    // 通用方法:倒入杯中
    private void pourInCup() {
        System.out.println("Pouring into cup...");
    }

    // 抽象方法:冲泡
    protected abstract void brew();

    // 抽象方法:添加调料
    protected abstract void addCondiments();

    // 钩子方法:是否需要添加调料
    protected boolean addCondimentsHook() {
        return true; // 默认需要添加调料
    }
}

2. 创建具体类
// 咖啡类
public class Coffee extends Beverage {
    @Override
    protected void brew() {
        System.out.println("Brewing coffee...");
    }

    @Override
    protected void addCondiments() {
        System.out.println("Adding sugar and milk...");
    }
}

// 茶类
public class Tea extends Beverage {
    @Override
    protected void brew() {
        System.out.println("Steeping tea leaves...");
    }

    @Override
    protected void addCondiments() {
        System.out.println("Adding lemon...");
    }

    // 重写钩子方法,不需要添加调料
    @Override
    protected boolean addCondimentsHook() {
        return false;
    }
}

3. 客户端代码
public class TemplateMethodExample {
    public static void main(String[] args) {
        System.out.println("Preparing Coffee:");
        Beverage coffee = new Coffee();
        coffee.prepareBeverage();

        System.out.println("\nPreparing Tea:");
        Beverage tea = new Tea();
        tea.prepareBeverage();
    }
}

输出结果
Preparing Coffee:
Boiling water...
Brewing coffee...
Pouring into cup...
Adding sugar and milk...

Preparing Tea:
Boiling water...
Steeping tea leaves...
Pouring into cup...

UML 类图

        +----------------------+
        |     Beverage         |<--------------------+
        +----------------------+                     |
        | + prepareBeverage()  |                     |
        | + brew()             | (Abstract Method)   |
        | + addCondiments()    |                     |
        | + addCondimentsHook()|                     |
        +----------------------+                     |
                ^                                    |
                |                                    |
    +------------------+                  +------------------+
    |      Coffee      |                  |       Tea        |
    +------------------+                  +------------------+
    | + brew()         |                  | + brew()         |
    | + addCondiments()|                  | + addCondiments()|
    +------------------+                  +------------------+

钩子方法

  • 钩子方法是一种可选的方法,允许子类对模板方法的某些行为进行控制。
  • 示例中,addCondimentsHook 用于决定是否添加调料。

使用场景

  1. 多个子类有类似行为:需要复用通用逻辑。
  2. 固定流程的实现:如数据处理管道、游戏回合处理等。
  3. 扩展性需求较高:新增行为只需创建子类。

优化与扩展

  1. 结合策略模式
    • 可将模板中可变部分抽取为策略,进一步提高灵活性。
  2. Spring 框架的应用
    • Spring 中大量使用了模板方法模式,如 JdbcTemplateRestTemplate 等。

小结

  • 模板方法模式通过提取公共逻辑,增强了代码复用性。
  • 子类只需实现变化部分,避免了重复代码。
  • 在需要固定流程和灵活扩展时,模板方法模式是首选方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/923885.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【大数据学习 | Spark-Core】RDD的缓存(cache and checkpoint)

1. 单应用缓存&#xff1a;cache 1.1 cache算子 cache算子能够缓存中间结果数据到各个executor中&#xff0c;后续的任务如果需要这部分数据就可以直接使用避免大量的重复执行和运算。 rdd 存储级别中默认使用的算子cache算子&#xff0c;cache算子的底层调用的是persist算子…

上海乐鑫科技一级代理商飞睿科技,ESP32-C61高性价比WiFi6芯片高性能、大容量

在当今快速发展的物联网市场中&#xff0c;无线连接技术的不断进步对智能设备的性能和能效提出了更高要求。为了满足这一需求&#xff0c;乐鑫科技推出了ESP32-C61——一款高性价比的Wi-Fi 6芯片&#xff0c;旨在为用户设备提供更出色的物联网性能&#xff0c;并满足智能设备连…

如何选择黑白相机和彩色相机

我们在选择成像解决方案时黑白相机很容易被忽略&#xff0c;因为许多新相机提供鲜艳的颜色&#xff0c;鲜明的对比度和改进的弱光性能。然而&#xff0c;有许多应用&#xff0c;选择黑白相机将是更好的选择&#xff0c;因为他们产生更清晰的图像&#xff0c;更好的分辨率&#…

ubuntu22开机自动登陆和开机自动运行google浏览器自动打开网页

一、开机自动登陆 1、打开settings->点击Users 重启系统即可自动登陆桌面 二、开机自动运行google浏览器自动打开网页 1、安装google浏览器 sudo wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb sudo dpkg -i ./google-chrome-stable…

MVC、EL、JSTL

1.MVC设计模式 三层&#xff1a; MVC&#xff1a; M&#xff08;Model&#xff09;模型&#xff1a;负责业务逻辑处理&#xff0c;数据库访问。 V&#xff08;View&#xff09;视图&#xff1a;负责与用户交互。 C&#xff08;Controller&#xff09;控制器&#xff1a;负责流程…

Python的3D可视化库 - vedo (3)visual子模块 点对象的可视化控制

文章目录 3 PointsVisual的方法3.1 对象属性3.1.1 顶点大小3.1.2 复制属性3.1.3 颜色设置3.1.4透明度设置 3.2 对象光效3.2.1 点的形状3.2.2 点的表面光效 3.3 尾随线和投影3.3.1 尾随线3.3.2 投影 3.4 给对象附加文字说明3.4.1 标注3.4.2 2D标注3.4.3 气泡说明3.4.4 旗标说明3…

MySQL系列之远程管理(安全)

导览 前言Q&#xff1a;如何保障远程登录安全一、远程登录的主要方式1. 用户名/口令2. SSH3. SSL/TLS 二、使用TLS协议加密连接1. 服务端2. 客户端 结语精彩回放 前言 在我们的学习或工作过程中&#xff0c;作为开发、测试或运维人员&#xff0c;经常会通过各类客户端软件&…

交通路口智能监测平台实现

目录 本文所有资源均可在该(https://www.aspiringcode.com/content?id17218996189491&uid3e852f876bcd45a4b3e8cf241260451b)处获取。 1.概述 交通要道的路口上人车穿行&#xff0c;特别是上下班早高峰&#xff0c;且时常发生交通事故。因此对交通路口的车流量和人流量的…

Qt Graphics View 绘图架构

Qt Graphics View 绘图架构 "QWGraphicsView.h" 头文件代码如下&#xff1a; #pragma once#include <QGraphicsView>class QWGraphicsView : public QGraphicsView {Q_OBJECTpublic:QWGraphicsView(QWidget *parent);~QWGraphicsView();protected:void mouseM…

获 2023 年度浙江省科学技术进步奖一等奖 | 网易数智日报

11 月 22 日&#xff0c;加快建设创新浙江因地制宜发展新质生产力动员部署会暨全省科学技术奖励大会在杭州隆重召开。浙江大学、网易数智等单位联合研发的“大规模结构化数据智能计算平台及产业化”项目获得 2023 年度浙江省科学技术进步奖一等奖。 加快建设创新浙江因地制宜发…

C++笔记之构造函数声明只需要写明需要的参数,不需要列出所有成员变量、可以使用成员初始化列表初始化所有需要的成员变量

C++笔记之构造函数声明只需要写明需要的参数,不需要列出所有成员变量、可以使用成员初始化列表初始化所有需要的成员变量 参考笔记 C++新特性探究(七):初始化列表(Initialization List) C++之关于初始化列表(Initialization List)的一个补充示例 C++笔记之构造函数声明只需要…

Element UI 打包探索【1】

目录 第一个命令 第二个命令 node build/bin/iconInit.js node build/bin/build-entry.js node build/bin/i18n.js node build/bin/version.js 总结 最近在接触组件库的项目&#xff0c;所以特意拿来Element UI借鉴学习一下&#xff0c;它算是做前端的同学们离不开的一…

使用Setup Factory将C#的程序打包成安装包

一、软件下载 https://download.csdn.net/download/qq_65356682/90042701 可以直接下载 二、软件使用 打开 1、创建一个新的项目 2、设置如下信息&#xff0c;也可以不设置&#xff0c;最好填非空的、 产品名就是你安装成功后生成文件的名称 3、如下文件夹路径就是你C#中ex…

QT实现拷贝复制文件操作 QT5.12.3环境 C++实现

案例需求&#xff1a;利用QT线程操作&#xff0c;实现拷贝复制文件操作 代码&#xff1a; myfile.h #ifndef MYFILE_H #define MYFILE_H#include <QObject> #include <QDebug> #include <QThread> #include <QFile> #include <QtWidgets> class…

vue 富文本图片如何拖拽

在Vue项目中实现富文本编辑器&#xff08;如vue-quill-editor&#xff09;的图片拖拽功能&#xff0c;需要结合Quill.js及其相关插件进行配置 安装必要的依赖包&#xff1a; 你需要安装vue-quill-editor作为富文本编辑器的基础组件。为了支持图片拖拽功能&#xff0c;你还需要…

Python基础学习-11函数参数

1、"值传递” 和“引用传递” 1&#xff09;不可变的参数通过“值传递”。比如整数、字符串等 2&#xff09;可变的参数通过“引用参数”。比如列表、字典。 3&#xff09;避免可变参数的修改 4&#xff09;内存模型简介 2、函数参数类型 1&#xff09; def func() #无参…

41_GAN网络详解(1)

生成对抗网络&#xff08;Generative Adversarial Network&#xff0c;简称GAN&#xff09;是一种深度学习模型&#xff0c;提出于2014年&#xff0c;由Ian Goodfellow及其团队提出。GAN通过对抗训练的方式&#xff0c;利用两个神经网络模型进行协作&#xff0c;达到生成高质量…

Top 10 Tools to Level Up Your Prompt Engineering Skills

此文章文字是转载翻译&#xff0c;图片是自已用AI 重新生成的。文字内容来自 https://www.aifire.co/p/top-10-ai-prompt-engineering-tools 供记录学习使用。 Introduction to AI Prompt Engineering AI Prompt Engineering 简介 1&#xff0c;Prompt Engineering 提示工程…

Redis设计与实现 学习笔记 第二十章 Lua脚本

Redis从2.6版本引入对Lua脚本的支持&#xff0c;通过在服务器中嵌入Lua环境&#xff0c;Redis客户端可以使用Lua脚本&#xff0c;直接在服务器端原子地执行多个Redis命令。 其中EVAL命令可以直接对输入的脚本进行求值&#xff1a; 而使用EVALSHA命令则可以根据脚本的SHA1校验…

【人工智能】Python常用库-Scikit-learn常用方法教程

Scikit-learn 是一个功能强大的机器学习库&#xff0c;支持数据预处理、分类、回归、聚类、降维等功能&#xff0c;广泛用于模型开发与评估。以下是 Scikit-learn 的常用方法及详细说明。 1. 安装与导入 安装 Scikit-learn&#xff1a; pip install scikit-learn导入基本模块…