模版方法模式详解:使用和实现的指南

目录

  • 模版方法模式
    • 模版方法模式结构
    • 模版方法模式适合应用场景
    • 模版方法模式优缺点
    • 练手题目
      • 题目描述
      • 输入描述
      • 输出描述
      • 题解

模版方法模式

模板方法模式是一种行为设计模式, 它在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。

类比真实世界中建造大量房屋。 标准房屋建造方案中可提供几个扩展点, 允许潜在房屋业主调整成品房屋的部分细节。

每个建造步骤 (例如打地基、 建造框架、 建造墙壁和安装水电管线等) 都能进行微调, 这使得成品房屋会略有不同。

在这里插入图片描述

模版方法模式结构

在这里插入图片描述

  1. 抽象类 (Abstract­Class) 会声明作为算法步骤的方法, 以及依次调用它们的实际模板方法。 算法步骤可以被声明为 抽象类型, 也可以提供一些默认实现。

  2. 具体类 (Concrete­Class) 可以重写所有步骤, 但不能重写模板方法自身。

一般,模版方法都加上final关键字,不允许被覆写。

通用代码结构

//抽象类定义了一个模板方法,其中通常会包含某个由抽象原语操作调用组成的算法框架。
public abstract class AbstractClass{//基本算法步骤protected abstract void step1();protected abstract void step2();//模版方法final public void templateMethod(){//算法基本逻辑this.step1();this.step2();...}
}// 具体类必须实现基类中的所有抽象操作,但是它们不能重写模板方法自身。
public class ConcreteClass1 extends AbstractClass{//实现基本方法protected abstract void step1(){...};protected abstract void step2(){....};
}public class ConcreteClass2 extends AbstractClass{//实现基本方法protected abstract void step1(){...};protected abstract void step2(){....};
}//客户端
public class Client{public static void main(String[] args){AbstractClass class1 = new ConcreteClass1();AbstractClass class2 = new ConcreteClass2();class1.templateMethod();class2.templateMethod();}
}

模版方法模式适合应用场景

  • 当你只希望客户端扩展某个特定算法步骤,而不是整个算法或其结构时,可使用模板方法模式。

  • 当多个类的算法除一些细微不同之外几乎完全一样时,你可使用该模式。但其后果就是,只要算法发生变化,你就可能需要修改所有的类。

在这里插入图片描述

**识别方法:**模版方法可以通过行为方法来识别,该方法已有一个在基类中定义的 “默认” 行为。

模版方法模式优缺点

模版方法模式的优点

  • 你可仅允许客户端重写一个大型算法中的特定部分, 使得算法其他部分修改对其所造成的影响减小。

  • 你可将重复代码提取到一个超类中。

模版方法模式的缺点

  • 部分客户端可能会受到算法框架的限制。

  • 通过子类抑制默认步骤实现可能会导致违反里氏替换原则

  • 模板方法中的步骤越多, 其维护工作就可能会越困难。

练手题目

题目描述

小明喜欢品尝不同类型的咖啡,她发现每种咖啡的制作过程有一些相同的步骤,他决定设计一个简单的咖啡制作系统,使用模板方法模式定义咖啡的制作过程。系统支持两种咖啡类型:美式咖啡(American Coffee)和拿铁(Latte)。

咖啡制作过程包括以下步骤:

  1. 研磨咖啡豆 Grinding coffee beans

  2. 冲泡咖啡 Brewing coffee

  3. 添加调料 Adding condiments

其中,美式咖啡和拿铁的调料添加方式略有不同, 拿铁在添加调料时需要添加牛奶Adding milk

输入描述

多行输入,每行包含一个数字,表示咖啡的选择(1 表示美式咖啡,2 表示拿铁)。

输出描述

根据每行输入,输出制作咖啡的过程,包括咖啡类型和各个制作步骤,末尾有一个空行。

在这里插入图片描述

题解

模版方法实现。

import java.util.Scanner;// 抽象类,定义咖啡制作的基本步骤
abstract class CoffeeModel {private String coffeeName;// 构造函数,接受咖啡名称参数public CoffeeModel(String coffeeName) {this.coffeeName = coffeeName;}protected abstract void grind();protected abstract void brew();protected abstract void addCondiments();// 添加其他调料可使用该类public void addThings(){};// 模板方法,定义咖啡制作的流程public final void createCoffeeTemplate() {System.out.println("Making " + coffeeName + ":");grind();brew();//根据情况,是否调用添加更多调料if (isAddThings()) {addThings(); }addCondiments();System.out.println();}// 默认不添加其他调料。如牛奶等public boolean isAddThings() {return false;}
}//美式咖啡类实现
class CreateAmericanCoffee extends CoffeeModel {public CreateAmericanCoffee() {super("American Coffee");}@Overrideprotected void grind() {System.out.println("Grinding coffee beans");}@Overrideprotected void brew() {System.out.println("Brewing coffee");}@Overrideprotected void addCondiments() {System.out.println("Adding condiments");}// 美式咖啡默认不添加其他调料,如牛奶等@Overridepublic boolean isAddThings() {return false; }
}//拿铁类实现
class CreateLatte extends CoffeeModel {private boolean addThingsFlag = true;public CreateLatte() {super("Latte");}@Overrideprotected void grind() {System.out.println("Grinding coffee beans");}@Overrideprotected void brew() {System.out.println("Brewing coffee");}@Overrideprotected void addCondiments() {System.out.println("Adding condiments");}//需要添加调料,牛奶@Overridepublic void addThings(){System.out.println("Adding milk");}// 拿铁默认添加牛奶@Overridepublic boolean isAddThings() {return this.addThingsFlag; }// 外部调用以改变是否添加牛奶的状态,钩子函数public void setAddThingsFlag(boolean flag) {this.addThingsFlag = flag;}
}public class Main {public static void main(String[] args) {try (Scanner scanner = new Scanner(System.in)) {while (scanner.hasNextInt()) {int input = scanner.nextInt();CoffeeModel coffee;switch (input) {case 1:coffee = new CreateAmericanCoffee();break;case 2:coffee = new CreateLatte();break;default:System.out.println("无效选择,请输入1或2");continue;}coffee.createCoffeeTemplate();}}}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《昇思25天学习打卡营第3天|张量 Tensor》

文章目录 前言:今日所学:1. 创建张量2. 张量的属性3.张量索引与运算4. NumPy与Tensor的转换5. 稀疏张量 前言: 张量?张亮?张量是什么? 张量是一个可以用来表示在一些矢量、标量和其他张量之间的线性关系的…

高并发部署:基于 Gunicorn、Flask 和 Docker

一、准备工作 确保已经安装以下软件: DockerDocker ComposePython 3.x 二、创建 Flask 应用 首先,创建一个简单的 Flask 应用。创建一个新的目录并在其中创建以下文件: 1. app.py python fromflask importFlask, jsonifyapp Flask(__…

leetcode 第133场双周赛 100333.统计逆序对的数目【计数dp/滚动数组/前缀和优化】

分析: 先考虑如下问题。 求长度为n,逆序对为m的排列数量。 可以考虑dp,dp[i][j]定义为长度为i,逆序对为j的排列数量。 dp[1][0] 1; //枚举排列长度,或者认为枚举当前需要插到长度为i-1的排列中的数字 for(int i 1…

OpenAI封杀不支持地区API:违规封号,7月9日生效

OpenAI 在检测用户使用其 API 的地区后,提示所有不支持位置的用户 昨晚,很多大模型应用的开发者、程序员都收到了 OpenAI 的警告信,心里一惊。 OpenAI 在检测用户使用其 API 的地区后,提示所有不支持位置的用户:即将封…

冒泡排序、选择排序、插入排序~java版

1、冒泡排序(Bubble Sort) 冒泡排序的基本思想是多次遍历待排序序列,每次遍历时两两比较相邻元素,如果顺序不对则交换,直到整个序列有序为止。 public class BubbleSort {public static void bubbleSort(int[] arr) …

图书管理系统(附源码)

前言:前面一起和小伙伴们学习了较为完整的Java语法体系,那么本篇将运用这些知识连串在一起实现图书管理系统。 目录 一、总体设计 二、书籍与书架 书籍(Book) 书架(Booklist) 三、对图书的相关操作 I…

已解决问题 | 该扩展程序未列在 Chrome 网上应用店中,并可能是在您不知情的情况下添加的

在Chrome浏览器中,如果你看到“该扩展程序未列在 Chrome 网上应用店中,并可能是在您不知情的情况下添加的”这样的提示,通常是因为该扩展程序没有通过Chrome网上应用店进行安装。以下是解决这个问题的步骤: 解决办法:…

Spring Boot整合Redis缓存的最佳实践

Spring Boot整合Redis缓存的最佳实践 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在现代应用开发中,缓存是提升系统性能和响应速度的关键技术之…

kali/ubuntu安装vulhub

无须更换源,安装docker-compose apt install docker.io docker -vdocker-compose #提示没有,输入y安装mkdir -p /etc/docker vi /etc/docker/daemon.json #更换dockerhub国内源┌──(root㉿kali)-[/home/kali/vulhub-master/tomcat/CVE-2017-12615] …

【VScode】常规插件安装

以下是VScode常规插件安装: C/C C/C extension pack C/C themes Draw.io integration highlight 以上插件安装完毕后,可实现 字体高亮,自动补齐,函数跳转,主题切换,图表生成等常用功能。

中介子方程三十七

XXFXXuXXWXXuXXdXXrXXαXXuXpXXKXηXiXXnXXyXηXyXXnXXiXηXKXXpXuXXαXXrXXdXXuXWXπXXWXeXyXeXbXπXpXXNXXqXeXXrXXαXXuXpXXKXηXiXXnXXyXηXyXXnXXiXηXKXXpXuXXαXXrXXeXqXXNXXpXπXbXeXyXeXWXXπXWXuXXdXXrXXαXXuXpXXKXηXiXXnXXyXηXyXXnXXiXηXKXXpXuXXαXXrXXdXXuXXW…

【TensorFlow深度学习】对比学习的核心:实例与上下文的对抗

对比学习的核心:实例与上下文的对抗 对比学习概述实例与上下文的对抗:核心机制实战代码示例:使用PyTorch实现SimCLR结语 在深度学习的浩瀚星海中,对比学习作为自我监督学习的一个分支,正以破竹之势引领着无标注数据利用…

dledger原理源码分析系列(三)-选主

简介 dledger是openmessaging的一个组件, raft算法实现,用于分布式日志,本系列分析dledger如何实现raft概念,以及dledger在rocketmq的应用 本系列使用dledger v0.40 本文分析dledger的选主 关键词 Raft Openmessaging 心跳/选…

SpringMVC中的异常处理器

文章目录 12异常处理器12.1基于配置的异常处理HandlerExceptionResolver接口直接在springmvc中声明使用 12.2基于注解的异常处理需要书写异常的配置类 12异常处理器 12.1基于配置的异常处理 HandlerExceptionResolver接口 接口实现类: DefaultHandlerExceptionR…

Linux安装redis教程(超级详细,新手必看)

环境: Centos 7.9 一、安装准备工作 1.配置gcc 安装redis前需要配置gcc: yum install gcc如果配置gcc出现依赖包问题,可以到主页查看帖子解决:https://blog.csdn.net/m0_59117906/article/details/134451622?spm1001.2014.300…

这四款软件很好用,可以提升工作、学习效率

TableConvert TableConvert是一个基于Web的在线表格转换工具,能够将多种格式的表格数据进行快速转换。它支持将Excel、URL、HTML、JSON、CSV等格式转换为Markdown表、CSV/TSV、XML、YAML、插入SQL、HTML、Excel和LaTeX等格式。用户只需将表格数据粘贴到编辑器&#…

设置HTML元素的背景颜色

设置HTML元素的背景颜色 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!在本文中,我们将探讨如何使用HTML和CSS来设置HTML元素的背景颜色。背景颜色…

本教程将指导如何通过 Vue 组件和后端 API 交互

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

常用TELNET命令及其应用

常用TELNET命令及其应用 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! TELNET是一种基于文本协议的网络协议,主要用于远程登录到网络设备和服务器…

计算机视觉全系列实战教程 (十五):使用opencv对视频进行基本处理

视频处理基本介绍 1、基本概述(1)opencv中视频处理的两个基础类(2)视频的属性:获取属性和设置属性 2、VideoCapture的介绍(1)Why( VideoCapture类的作用)(2)How( 如何使用VideoCapture)A.播放视频文件函数B.播放视频文件并实现暂停和继续 3、VideoWriter类的介绍(1)…