设计模式之模版方法

模版方法介绍

模版方法(Template Method)模式是一种行为型设计模式它定义了一个操作(模板方法)的基本组合与控制流程,将一些步骤(抽象方法)推迟到子类中,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。这种设计方式将特定步骤的具体实现与操作流程分离开来,实现了代码的复用和扩展,从而提高代码质量和可维护性。

1、模版方法模式的定义与原理

模版方法模式原始定义是:在操作中定义算法的框架,将一些步骤推迟到子类中。模版方法让子类在不改变算法结构的情况下重新定义算法的某些步骤。这里的算法可以理解为广义上的业务逻辑,并不是特指某一个实际的算法。

模版方法模式的主要原理包括:

  • 抽象父类:定义一个算法所包含的所有步骤,并提供一些通用的方法逻辑。
  • 具体子类:继承自抽象父类,根据需要重写父类提供的算法步骤中的某些步骤。

2、模版方法模式的角色

模版方法模式包含以下主要角色:

  • 抽象类(Abstract Class):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。
  • 模板方法(Template Method):定义了算法的骨架,按某种顺序调用其包含的基本方法。
  • 基本方法(Concrete Method):在抽象类中已经实现的方法,为算法的各个步骤提供默认实现。
  • 抽象方法(Abstract Method):在抽象类中声明,由具体子类实现的方法,用于算法的某些特定步骤。
  • 钩子方法(Hook Method):在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。钩子方法提供了算法框架中的扩展点,允许子类在不改变算法结构的情况下,通过重写这些方法来自定义算法的行为。

3、模版方法模式的优点与缺点

优点
  1. 提高代码复用性:所有的子类可以复用父类中提供的模板方法代码。
  2. 提高扩展性:框架通过模板模式提供功能扩展点,让框架用户可以在不修改框架源码的情况下,基于扩展点定制化框架的功能。
  3. 明确算法结构:通过模板方法,可以清晰地定义算法的框架和步骤,使得算法的结构更加明确和易于理解。
缺点
  1. 类数量增加:由于每个算法都需要一个抽象类和具体子类来实现,因此在操作流程比较多时可能导致类的数量急剧增加,从而导致代码的复杂性提高。
  2. 关联性高:模板方法与子类实现的抽象方法紧密相关,如果该模板方法需要修改,可能会涉及到多个子类的修改。

4、模版方法模式的应用场景

模版方法模式适用于以下场景:

  • 当多个类有共同的算法结构,但具体的实现步骤可能有所不同时。
  • 当需要在不改变算法结构的情况下,对算法的某些步骤进行定制时。
  • 当需要提高代码的复用性和扩展性时。

例如,在软件开发中,经常需要处理各种业务逻辑流程,这些流程通常具有相似的结构但具体的实现步骤可能因业务需求的不同而有所差异。此时,可以使用模版方法模式来定义这些流程的框架和步骤,然后通过不同的子类来实现具体的业务逻辑。这样可以减少代码的重复,提高代码的可维护性和可扩展性。

二、模版方法实现例子

以下是一个用Java编写的模版方法模式的例子。在这个例子中,我们将创建一个抽象类Game,它定义了一个游戏的基本流程(即模版方法),包括初始化游戏、玩游戏和结束游戏等步骤。然后,我们创建两个具体的游戏类VideoGameBoardGame,它们分别实现了这些步骤中的特定行为。

// 抽象游戏类  
abstract class Game {  
  
    // 模版方法,定义了游戏的流程  
    final void play() {  
        initializeGame();  
        while (!gameOver()) {  
            playStep();  
        }  
        endGame();  
    }  
  
    // 抽象方法,需要子类实现  
    abstract void initializeGame();  
  
    // 抽象方法,需要子类实现  
    abstract void playStep();  
  
    // 抽象方法,判断游戏是否结束,可以提供一个默认实现,也可以留空让子类实现  
    abstract boolean gameOver();  
  
    // 钩子方法,可以在需要时由子类重写  
    void endGame() {  
        System.out.println("Game Over!");  
    }  
}  
  
// 视频游戏类  
class VideoGame extends Game {  
  
    @Override  
    void initializeGame() {  
        System.out.println("Initializing Video Game...");  
    }  
  
    @Override  
    void playStep() {  
        System.out.println("Playing Video Game Step...");  
        // 这里可以添加更多的游戏步骤逻辑  
    }  
  
    @Override  
    boolean gameOver() {  
        // 这里简化为总是返回true以结束游戏  
        // 在实际游戏中,这里应该包含判断游戏是否结束的逻辑  
        return true;  
    }  
  
    // 可以选择重写钩子方法以提供自定义的结束游戏逻辑  
    // 但在这个例子中,我们使用父类的默认实现  
}  
  
// 桌游类  
class BoardGame extends Game {  
  
    @Override  
    void initializeGame() {  
        System.out.println("Setting up Board Game...");  
    }  
  
    @Override  
    void playStep() {  
        System.out.println("Playing Board Game Turn...");  
        // 这里可以添加更多的游戏回合逻辑  
    }  
  
    @Override  
    boolean gameOver() {  
        // 这里简化为总是返回true以结束游戏  
        // 在实际游戏中,这里应该包含判断游戏是否结束的逻辑  
        return true;  
    }  
  
    // 同样,可以选择重写钩子方法  
}  
  
// 客户端类  
public class TemplateMethodPatternDemo {  
    public static void main(String[] args) {  
        Game videoGame = new VideoGame();  
        System.out.println("Playing Video Game:");  
        videoGame.play();  
  
        Game boardGame = new BoardGame();  
        System.out.println("\nPlaying Board Game:");  
        boardGame.play();  
    }  
}

在这个例子中,Game类定义了一个游戏的模版方法play(),它按照初始化游戏、玩游戏步骤(循环直到游戏结束)、结束游戏的顺序来执行。initializeGame()playStep()gameOver()是抽象方法,需要由子类来实现具体的游戏逻辑。endGame()是一个钩子方法,它提供了一个默认的实现,但子类可以根据需要重写它。

VideoGameBoardGame类分别实现了Game类的抽象方法,以提供各自的游戏逻辑。在main方法中,我们创建了VideoGameBoardGame的实例,并调用了它们的play()方法来玩游戏。由于play()方法是final的,因此它不能被子类重写,这保证了游戏流程的一致性。然而,通过重写抽象方法和钩子方法,子类可以灵活地实现自己的游戏逻辑。

如果觉得不错,记得点赞收藏,你们的反馈是我不断创作的动力。

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

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

相关文章

C语言下的文件详解

主要内容 文件概述文件指针文件的打开与关闭文件的读写 文件 把输入和输出的数据以文件的形式保存在计算机的外存储器上,可以确保数据能随时使用,避免反复输入和读取数据 文件概述 文件是指一组相关数据的有序集合 文件是存储数据的基本单位&#…

# mysql 中文乱码问题分析

mysql 中文乱码问题分析 一、问题分析: MySQL 中文乱码通常是因为字符集设置不正确导致的。MySQL 有多种字符集,如 latin1、utf8、utf8mb4 等,如果在创建数据库、数据表或者字段时没有指定正确的字符集,或者在插入数据时使用了与…

关于Java异常机制及finally关键字的详解

异常机制(Exception) 软件程序在运行过程中,非常可能遇到异常问题。常见的异常: 1、用户输入错误 2、设备错误 3、硬件问题,例如打印机关掉、服务器问题 4、物理限制:磁盘满了 Java是采用面向对象的方式来处理异常的。 处理过程…

哈希表——C语言

哈希表(Hash Table)是一种高效的数据结构,能够在平均情况下实现常数时间的查找、插入和删除操作。 哈希表的核心是哈希函数,哈希函数是一个将输入数据(通常称为“键”或“key”)转换为固定长度的整数的函数…

使用vue3-treeselect问题

1.当vue3-treeselect是单选时,使用watch监听绑定value,无法监听到值清空 对照后将:value改为v-model,如图 2.使用vue3-treeselect全部清空按钮如何置空select的值,使用watch监听 多选:pageInfo.officeName(val) {// …

【Linux进阶】文件系统6——理解文件操作

目录 1.文件的读取 1.1.目录 1.2.文件 1.3.目录树读取 1.4.文件系统大小与磁盘读取性能 2.增添文件 2.1.数据的不一致(Inconsistent)状态 2.2.日志式文件系统(Journaling filesystem) 3.Linux文件系统的运行 4、文件的删…

Java--方法重写

1.方法的重写首先需要有继承关系,且为子类重写父类的方法 2.方法名必须相同 3.参数列表必须相同 4.修饰符的范围可以扩大但不能缩小,public>protected>default>private,即父类的属性可以从private改为public,但不能反过来 5.抛出…

python爬虫入门(四)之Beautiful Soup库

一、什么是Beautiful Soup库 1、Beautiful Soup库是用来做HTML解析的库 Beautiful Soup把看起来复杂的HTML内容,解析成树状结构,让搜索和修改HTML结构变得更容易 2、第三方库,先安装 终端输入pip install bs4 from bs4 import Beautiful…

Cyber Weekly #14:WAIC 2024

赛博新闻 1、WAIC2024开幕:一半机器人,一半大模型 7月4日,AI界春晚——2024世界人工智能大会(WAIC 2024)在上海开幕,大会展示了500家企业的1500项展品,突出了机器人和大模型技术。国产机器人和…

【排序算法】—— 快速排序

快速排序的原理是交换排序,其中qsort函数用的排序原理就是快速排序,它是一种效率较高的不稳定函数,时间复杂度为O(N*longN),接下来就来学习一下快速排序。 一、快速排序思路 1.整体思路 以升序排序为例: (1)、首先随…

学生管理系统(通过顺序表,获取连续堆区空间实现)

将学生的信息,以顺序表的方式存储(堆区),并且实现封装函数 : 1】顺序表的创建, 2】判满、 3】判空、 4】往顺序表里增加学生信息、 5】遍历学生信息 6】任意位置插入学生信息 7】任意位置删除学生信…

【大模型LLM面试合集】大语言模型基础_llm概念

1.llm概念 1.目前 主流的开源模型体系 有哪些? 目前主流的开源LLM(语言模型)模型体系包括以下几个: GPT(Generative Pre-trained Transformer)系列:由OpenAI发布的一系列基于Transformer架构…

对话大模型Prompt是否需要礼貌点?

大模型相关目录 大模型,包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步,扬帆起航。 基于Dify的QA数据集构建(附代码)Qwen-2-7B和GLM-4-9B&#x…

Android OpenGL ES 离屏幕渲染1——EGL环境的创建,以及基础概念的理解

创建EGL上下文、配置EGL环境、创建EGL DISPLAY 什么是EGL: 由于OpenGL ES并不负责窗口管理以及上下文管理,该职责由各个平台自行完成;在Android平台下OpenGL ES的上下文环境是依赖EGL的API进行搭建的。 对于EGL这个框架,谷歌已经提…

WAWA鱼曲折的大学四年回忆录

声明:本文内容纯属个人主观臆断,如与事实不符,请参考事实 前言: 早想写一下大学四年的总结了,但总是感觉无从下手,不知道从哪里开始写,通过这篇文章主要想做一个记录,并从现在的认…

那些年背过的面试题——MySQL篇

本文是技术人面试系列 MySQL 篇,面试中关于 MySQL 都需要了解哪些基础?一文带你详细了解,欢迎收藏! WhyMysql? NoSQL 数据库四大家族 列存储 Hbase K-V 存储 Redis 图像存储 Neo4j 文档存储 MongoDB 云存储 OSS …

【Gin】项目搭建 一

环境准备 首先确保自己电脑安装了Golang 开始项目 1、初始化项目 mkdir gin-hello; # 创建文件夹 cd gin-hello; # 需要到刚创建的文件夹里操作 go mod init goserver; # 初始化项目,项目名称:goserver go get -u github.com/gin-gonic/gin; # 下载…

C++入门7——string类详解

目录 1.什么是string类? 2.string类对象的常见构造 2.1 string(); 2.2 string (const char* s); 2.3 string (const string& str); 2.4 string (const string& str, size_t pos, size_t len npos); 2.5 string (const char* s, size_t n); 2.7 验证…

模块一SpringBoot(一)

maven记得配置本地路径和镜像 IJ搭建 SpringIntiallizer--》将https://start.spring.io改成https://start.aliyun.com/ 项目结构 Spring有默认配置, application.properties会覆盖默认信息: 如覆盖端口号server.port8888

一个最简单的comsol斜坡稳定性分析例子——详细步骤

一个最简单的comsol斜坡稳定性分析例子——详细步骤 标准模型例子—详细步骤 线弹性模型下的地应力平衡预应力与预应变、土壤塑性和安全系数求解的辅助扫描