设计模式-模版方法

embedded/2025/2/14 1:20:53/

一、定义

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

模版方法模式是很常见且很有用的一种模式,理解起来也容易。其优点就是保护了这个算法的结构,重复的步骤在自身实现,一些步骤放给子类去实现,很灵活。

二、实现

以冲泡茶喝咖啡这两种饮料为例,二者都是咖啡因饮料,步骤为

茶:1、把水煮沸;2、用沸水浸泡茶叶;3、把茶倒进杯子;4、加柠檬

咖啡:1、把水煮沸;2、用沸水冲泡咖啡;3、把咖啡倒进杯子;4、加糖和牛奶

很明显看到,其中步骤1和3是重复的,步骤2和4是不一样的,基于此我们用模版方法模式来实现

java">//咖啡因饮料类,就是抽象父类
public abstract class CaffeineBeverage {//制作饮料public final void makeBeverage(){boilWater();brew();pourInCup();addCondiments();}//泡饮料public abstract void brew();//加入调料public abstract void addCondiments();public void boilWater(){System.out.println("烧水");}public void pourInCup(){System.out.println("把饮料倒进杯子中");}
}//咖啡类,具体的实现
public class Coffee extends CaffeineBeverage{@Overridepublic void brew() {System.out.println("冲泡咖啡");}@Overridepublic void addCondiments() {System.out.println("加入糖和牛奶");}
}//茶类,具体的实现
public class Coffee extends CaffeineBeverage{@Overridepublic void brew() {System.out.println("冲泡咖啡");}@Overridepublic void addCondiments() {System.out.println("加入糖和牛奶");}
}

测试:

java">public class TemplateTest {public static void main(String[] args) {test();}static void test(){CaffeineBeverage coffee = new Coffee();CaffeineBeverage tea = new Tea();System.out.println("======制作咖啡=====");coffee.makeBeverage();System.out.println("=====制作茶=====");tea.makeBeverage();}
}//输出结果
======制作咖啡=====
烧水
冲泡咖啡
把饮料倒进杯子中
加入糖和牛奶
=====制作茶=====
烧水
泡茶
把饮料倒进杯子中
加入柠檬

这样就实现了模版方法模式

三、钩子

钩子是一种被声明在抽象基类中的方法,但是只有空或者默认的实现,子类可以选择是否进行重写钩子函数。

钩子有很多用途,让子类更加灵活地控制算法流程,子类可以选择使用基类默认的钩子方法,也可以自己重写,提高了灵活度。

比如,我们在咖啡因饮料抽象基类中添加一个钩子,来表示是否加入调料。

java">public abstract class CaffeineBeverage {//制作饮料public final void makeBeverage(){boilWater();brew();pourInCup();if(addCondimentsFlag()){addCondiments();}}//是否加入调料,默认加入public boolean addCondimentsFlag(){return true;}//......
}

咖啡类我们不改变,默认加入,而茶类我们想让用户选择是否加入调料。

java">public class Tea extends CaffeineBeverage{private boolean addCondimentsFlag = false;public Tea(){}//可以让客户选择是否加入调料public Tea(boolean addCondimentsFlag) {this.addCondimentsFlag = addCondimentsFlag;}@Overridepublic boolean addCondimentsFlag() {return this.addCondimentsFlag;}
}

测试

java">public class TemplateTest {public static void main(String[] args) {testHook();}static void testHook(){CaffeineBeverage noCondimentsTea = new Tea(false);System.out.println("===不要调料的茶===");noCondimentsTea.makeBeverage();CaffeineBeverage hasCondimentsTea = new Tea(true);System.out.println("===要调料的茶===");hasCondimentsTea.makeBeverage();}
}//输出结果
===不要调料的茶===
烧水
泡茶
把饮料倒进杯子中
===要调料的茶===
烧水
泡茶
把饮料倒进杯子中
加入柠檬

http://www.ppmy.cn/embedded/162010.html

相关文章

TCP/IP参考模型和网络协议

由于国防部担心他们一些重要的主机、路由器和互联网关可能会突然崩溃,所以网络必须实现的另一目标是网络不受子网硬件损失的影响,已经建立的会话不会被取消,而且整个体系结构必须相当灵活。 TCP/IP是一组用于实现网络互连的通信协议。Interne…

什么是http请求中的session

一、引言 在现代Web开发中,Session是一个非常重要的概念。它允许服务器在多个HTTP请求之间保持用户状态,解决了HTTP协议无状态的问题。本文将详细介绍Session的工作原理、具体使用场景,并通过HTTP请求的例子来阐述其应用。 二、Session概述…

同.NET 8一起发布的C#12语法中新特性及用法演示

1. 主构造函数(Primary Constructors) 简化构造函数定义,允许在类或结构中直接声明构造函数参数。 示例: csharp public class Person(string name, int age) { public string Name > name; public int Age > age; } 2. …

vue3学习之待办事项列表(Todo List)

通过vite创建vue3项目&#xff0c;具体查看vite官网&#xff0c;安装依赖&#xff0c;引入element组件&#xff0c;操作查看elementPlus components下创建TodoList组件 <template><div class"todo-list"><h1>Todo List</h1><p class&quo…

【C++语言】C++入门

一、命名空间 在 C/C 中&#xff0c;变量、函数和后面的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化&#xff0c;用于避免命名冲突或者名字污染&#xff0c;na…

HarmonyOS第一课第二章习题答案

判断 1. 如果代码中涉及到一些网络、数据库、传感器等功能的开发&#xff0c;均可使用预览器进行预览。 答案&#xff1a;错误 2. module.json5文件中的deviceTypes字段中&#xff0c;配置了phone&#xff0c;tablet&#xff0c;2in1等多种设备类型&#xff0c;才能进行多设…

SickOs 1.2靶机(超详细教学)

靶机地址&#xff1a;https://www.vulnhub.com/entry/sickos-12,144/ 一、主机发现 使用 arp-scan -l查找靶机ip地址 靶机ip地址为192.168.55.146 攻击机的ip地址为192.168.55.129 二、进行端口扫描、目录枚举、指纹识别 1.端口扫描 nmap 192.168.55.146发现靶机只有22和…

机器学习数学基础:22.对称矩阵的对角化

一、核心概念详解 &#xff08;一&#xff09;内积 定义与公式&#xff1a;在 n n n维向量空间中&#xff0c;对于向量 x ⃗ ( x 1 , x 2 , ⋯ , x n ) \vec{x}\ (x_1,x_2,\cdots,x_n) x (x1​,x2​,⋯,xn​)和 y ⃗ ( y 1 , y 2 , ⋯ , y n ) \vec{y}\ (y_1,y_2,\cdots,y_…