程序员必知的23种设计模式之模板模式

2023-11-13

1. 模式引出-豆浆制作问题

编写制作豆浆的程序,说明如下:

  1. 制作豆浆的流程 选材—>添加配料—>浸泡—>放到豆浆机打碎

  2. 通过添加不同的配料,可以制作出不同口味的豆浆,也可以不添加调料

  3. 选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的

  4. 请使用 模板方法模式 完成 (说明:因为模板方法模式,比较简单,很容易就想到这个方案,因此就直接使用,不再使用传统的方案来引出模板方法模式 )

2. 模板方法模式基本介绍
  1. 模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern),z在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

  2. 简单说,模板方法模式 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤

  3. 这种类型的设计模式属于行为型模式。

2.1 模板方法模式的原理类图

在这里插入图片描述

对原理类图的说明-即(模板方法模式的角色及职责)

  1. AbstractClass 抽象类, 类中实现了模板方法(template),定义了算法的骨架,具体子类需要去实现 其它的抽象方法operationr2,3,4

  2. ConcreteClass 实现抽象方法operationr2,3,4, 以完成算法中特点子类的步骤

  3. 子类也可以将方法实现为空方法,这就称作钩子方法

2.2 模板方法模式的钩子方法
  1. 在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为“钩子”。

  2. 比如,我们还希望制作纯豆浆,不添加任何的配料,就可以使用钩子方法对前面的模板方法进行改造

3. 方案实现

UML类图

在这里插入图片描述

SoyaMilk.java

//抽象类,表示豆浆
public abstract class SoyaMilk {

	// 模板方法, make , 模板方法可以做成final , 不让子类去覆盖.
	public final void make() {
		System.out.println("----开始制作----");
		select();
		if (WantaddCondiments())
			addCondiments();
		soak();
		beat();
	}

	// 选材料
	public void select() {
		System.out.println("第一步:选择好的新鲜黄豆  ");
	}

	// 添加不同的配料, 抽象方法, 子类具体实现
	public abstract void addCondiments();

	// 浸泡
	public void soak() {
		System.out.println("第三步, 开始浸泡, 需要3小时 ");
	}

	public void beat() {
		System.out.println("第四步:放到豆浆机去打碎  ");
	}

	// 钩子方法
	public boolean WantaddCondiments() {
		return true;
	}
}

PeanutSoyMilk.java

// 具体豆浆
public class PeanutSoyMilk extends SoyaMilk {
	@Override
	public void addCondiments() {
		System.out.println("第二步:加入花生");

	}
}

RedBeanSoyMilk.java

// 具体豆浆
public class RedBeanSoyMilk extends SoyaMilk {
	@Override
	public void addCondiments() {
		System.out.println("第二步:加入红豆");

	}
}

PureSoyaMilk.java

public class PureSoyaMilk extends SoyaMilk{

	@Override
	public void addCondiments() {
		
	}
	
	@Override
	public boolean WantaddCondiments() {
		return false;
	}

}

测试Main.java

public class Main {
	public static void main(String[] args) {
		RedBeanSoyMilk milk = new RedBeanSoyMilk();
		milk.make();
		PeanutSoyMilk milk2 = new PeanutSoyMilk();
		milk2.make();
		PureSoyaMilk milk3 = new PureSoyaMilk();
		milk3.make();
	}

}

输出结果

在这里插入图片描述

4. 模板方法模式在Spring4框架的应用

Spring4中有一个AbstractApplicationContext抽象类体现了模板模式

public abstract class AbstractApplicationContext ...{
	...
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		prepareRefresh();
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
		prepareBeanFactory(beanFactory);
		try {
			postProcessBeanFactory(beanFactory);
			invokeBeanFactoryPostProcessors(beanFactory);
			registerBeanPostProcessors(beanFactory);
			...
			...
            ...
}

refresh方法中排列着其他方法,其中postProcessBeanFactory方法是由ConfigurableApplicationContext接口继承而来,但是在此类中实现为空实现,该方法其实就是一个钩子方法,由子类决定是否重写

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}

该类中还有一个方法ConfigurableListableBeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	refreshBeanFactory();
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	if (logger.isDebugEnabled()) {
		logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
	}
	return beanFactory;
}

其中的refreshBeanFactory()就是本类中的一个抽象方法,需要子类重写

protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
5. 模板方法模式的注意事项和细节
  1. 基本思想是:算法只存在于一个地方,也就是在父类中,容易修改。需要修改算法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改

  2. 实现了最大化代码复用。父类的模板方法和已实现的某些步骤会被子类继承而直接使用。

  3. 既统一了算法,也提供了很大的灵活性。父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步骤的实现。

  4. 该模式的不足之处:每一个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大

  5. 一般模板方法都加上final关键字, 防止子类重写模板方法.

  6. 模板方法模式使用场景:当要完成在某个过程,该过程要执行一系列步骤 ,这一系列的步骤基本相同,但其个别步骤在实现时 可能不同,通常考虑用模板方法模式来处理

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

程序员必知的23种设计模式之模板模式 的相关文章

随机推荐

  • dz论坛伪静态加http跳转https遗留问题apache配置ssl

    一 首先 申请并且配置好服务器ssl证书 阿里 腾讯都有免费的 同时都有教程 下载apache格式的证书 解压后放到d ssl 目录 打开 D phpStudy Apache conf httpd conf 在最后面添加SSL配置
  • 2.基于原型的聚类方法

    基于原型的聚类方法 文章目录 一 概念 二 K Means 2 1 算法流程 2 2 超参数 2 3 特性 2 4 解析 2 5 K Means 2 6 Python实现 三 K Mediods 3 1 概念 3 2 算法对比 四 特性 一
  • android实现每天定时提醒的功能

    有时开发中有这样的需求 每天几点定时提醒等等 下面就来实现这个功能 首先新建一个广播接收者 public class AlarmReceiver extends BroadcastReceiver Override public void
  • 案例——UDP聊天

    UDP聊天案例 做一个网络编程相关的案例 想着用利用UDP的快速且不用连接的优点做一个聊天室 我们一个聊天程序需要可以接收消息 也要可以发送消息 所以我们的DatagramSocket对象不但需要调用send函数 还需要调用recieve函
  • 【C语言】qsort 快速排序函数(详解+用法+my_qsort函数模拟实现)

    本文详细讲解qsort函数用法 并包含很多知识细节 干活满满 文章目录 qsort函数功能 qsort函数声明 函数指针 qsort函数用法 整型 浮点型 字符型 字符串型 结构体型 my qsort函数模拟实现 qsort函数功能 排序是
  • 【数据分析】基于RFM模型的线上零售中的客户细分(一):客户细分

    基于RFM模型的线上零售中的客户细分 一 简介 RFM模型通常被用来衡量客户价值和客户创利能力 是商业数据分析中的重要工具和手段 这次我将使用RFM模型对线上零售数据进行客户细分 本篇博客是关于客户细分的相关介绍 具体实例项目将在下一篇博客
  • mutable和volatile

    mutable变量永远处于可变的状态 mutable在类中只能修饰非静态数据成员 即使是在const函数中 甚至是const结构体变量或类对象 其mutable成员也可以被修改 我们知道 如果类的成员函数不会改变对象的状态 那么这个成员函数
  • Feedsky 上 csdn blog 订阅数排名 (zz)

    1114356 programmer editor http blog csdn net programmer editorhttp feeds feedsky com csdn net programmer editor 23897 po
  • matlab_ga(),matlab遗传算法ga函数

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 function optimization4 A b Aeq beq LB 0 1 0 03 0 03 0 1 0 03 0 03 UB 0 4 0 06 0 06 0 4 0 06 0 06
  • python+selenium自动化测试框架实例_顶Python+Selenium搭建UI自动化测试框架

    Python语言是非常强大的编程语言 很多时候也拿来当脚本语言用 Selenium是web应用测试工具 支持Java Python等多种语言脚本 支持Chrome Firefox等多种主流浏览器 主要实现的就是模拟人使用web应用 自动的打
  • 解决Windows11能登录QQ微信,但不可以使用浏览器上网

    解决浏览器不能上网 报错ERR PROXY CONNECTION FAILED 首先我们看到我们的以太网显示连接正常 但是 但我们打开谷歌浏览器是这样的 当我们打开IE是这样的 然后它们都报同样一个错误 ERR PROXY CONNECTI
  • 企业级Nginx+keepalived 双主架构笔记参考

    对于主备架构 始终存在一台服务器处于空闲状态 对于企业来说 资源分配就不很合理 如果要将两台服务器都利用起来 可以使用主主架构的方式 同时2台都对外服务 拥有2个VIP地址 同时接收用户的请求 双主架构的实现步骤参考 master1 反向代
  • leetcode 1812. Determine Color of a Chessboard Square(python)

    描述 You are given coordinates a string that represents the coordinates of a square of the chessboard Below is a chessboar
  • phpqrcode固定二维码大小

    我们都知道一个二维码PHP API接口使用phpqrcode php文件编写很容易就可以写出一个API接口 网页所出现的二维码图像一般都是随内容的增加而增加 我想要一个固定的png图像尺寸大小 怎么办 一般网上都会给出答案说确定img的尺寸
  • Android 内存泄露实践分析

    http wetest qq com lab view 161 html from adsout qqtips past2 sessionUserType BFT PARAMS 199168 TASKID ADUIN 576439313 A
  • Unity发布WebGL如何本地打开

    https blog csdn net blastblade article details 81170020
  • 淘宝镜像的使用

    1 切换淘宝镜像 npm config get registry 2 设置淘宝镜像 npm config set registry https registry npmirror com
  • 用java写一个多线程可断点续传的下载方法

    好的 我可以向你提供一个基本的多线程可断点续传的下载方法 首先 你需要创建一个线程类 用于下载文件的指定部分 这个线程类需要记录文件的开始和结束位置 并且在运行时使用这些位置来设置 HTTP 请求的 Range 头部 然后 你可以创建一个主
  • 搭建jeesite开发环境

    jeesite tomcat7 mysql eclipse maven jeesite下载路径 https github com thinkgem jeesite 下载jeesite并解压 在D 01 Projects 06 jeesite
  • 程序员必知的23种设计模式之模板模式

    文章目录 1 模式引出 豆浆制作问题 2 模板方法模式基本介绍 2 1 模板方法模式的原理类图 2 2 模板方法模式的钩子方法 3 方案实现 4 模板方法模式在Spring4框架的应用 5 模板方法模式的注意事项和细节 1 模式引出 豆浆制