行为型设计模式(一)模版方法模式 迭代器模式

模板方法模式 Template

1、什么是模版方法模式

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

2、为什么使用模版方法模式

  1. 封装不变部分:模版方法模式将算法的不变部分封装在父类中,使得子类只需要实现变化的部分,提高了代码的复用性。
  2. 扩展性:子类可以通过重写父类的方法来扩展或修改算法的行为,提高了灵活性。
  3. 避免代码重复:将相同的代码放在父类中,避免了在每个子类中重复相同的代码。

3、如何使用模版方法模式

设计实现一个制作咖啡的场景,其中一些步骤是相同的,而一些不同的步骤可以由子类重写

// 模板类
abstract class CoffeeTemplate {// 模板方法,定义咖啡的制作步骤final void makeCoffee() {boilWater();brewCoffeeGrounds();pourInCup();addCondiments();}// 具体步骤,煮沸水void boilWater() {System.out.println("Boiling water");}// 具体步骤,冲泡咖啡void brewCoffeeGrounds() {System.out.println("Brewing coffee grounds");}// 具体步骤,倒入杯中void pourInCup() {System.out.println("Pouring into cup");}// 具体步骤,添加调料,子类实现abstract void addCondiments();
}// 具体子类,制作茶
class TeaTemplate extends CoffeeTemplate {@Overridevoid addCondiments() {System.out.println("Adding lemon");}
}// 具体子类,制作咖啡
class CoffeeTemplateImpl extends CoffeeTemplate {@Overridevoid addCondiments() {System.out.println("Adding sugar and milk");}
}// 客户端代码
public class Client {public static void main(String[] args) {CoffeeTemplate tea = new TeaTemplate();tea.makeCoffee();CoffeeTemplate coffee = new CoffeeTemplateImpl();coffee.makeCoffee();}
}

4、是否存在缺陷和不足

  1. 限制子类:模版方法模式可能限制了子类的灵活性,因为在这个模式中要求子类必须遵循父类定义的算法骨架。
  2. 难以维护:如果模版方法变得复杂,可能会导致难以维护和理解。

5、如何缓解缺陷和不足

  1. 使用钩子方法:在模版方法中引入钩子方法,允许子类选择性地实现或者覆盖某些步骤,提高灵活性。
// 模板类
abstract class CoffeeTemplate {// 模板方法,定义咖啡的制作步骤final void makeCoffee() {boilWater();brewCoffeeGrounds();pourInCup();if (customerWantsCondiments()) {addCondiments();}}// 具体步骤,煮沸水void boilWater() {System.out.println("Boiling water");}// 具体步骤,冲泡咖啡void brewCoffeeGrounds() {System.out.println("Brewing coffee grounds");}// 具体步骤,倒入杯中void pourInCup() {System.out.println("Pouring into cup");}// 具体步骤,添加调料,子类实现abstract void addCondiments();// 钩子方法,决定是否添加调料,默认添加boolean customerWantsCondiments() {return true;}
}// 具体子类,制作茶
class TeaTemplate extends CoffeeTemplate {@Overridevoid addCondiments() {System.out.println("Adding lemon");}// 通过重写钩子方法,决定是否添加调料@Overrideboolean customerWantsCondiments() {// 用户不想要调料return false;}
}// 具体子类,制作咖啡
class CoffeeTemplateImpl extends CoffeeTemplate {@Overridevoid addCondiments() {System.out.println("Adding sugar and milk");}
}// 客户端代码
public class Client {public static void main(String[] args) {CoffeeTemplate tea = new TeaTemplate();tea.makeCoffee();CoffeeTemplate coffee = new CoffeeTemplateImpl();coffee.makeCoffee();}
}
// 使用钩子方法 customerWantsCondiments 来判断是否执行添加调料的步骤,然后在 TeaTemplate 中
// 重写钩子方法,用户可以选择是否添加。CoffeeTemplateImpl 中没有重写钩子方法,就默认执行
  1. 使用策略模式:考虑将某些步骤设计成策略对象,允许在运行时切换算法的实现。
// 策略接口,调料的添加策略
interface CondimentsStrategy {void addCondiments();
}// 具体的调料策略,添加柠檬
class LemonCondiments implements CondimentsStrategy {@Overridepublic void addCondiments() {System.out.println("Adding lemon");}
}// 具体的调料策略,添加糖和牛奶
class SugarAndMilkCondiments implements CondimentsStrategy {@Overridepublic void addCondiments() {System.out.println("Adding sugar and milk");}
}// 模板类
abstract class CoffeeTemplate {// 策略对象,用于调料的添加private CondimentsStrategy condimentsStrategy;// 设置调料策略void setCondimentsStrategy(CondimentsStrategy condimentsStrategy) {this.condimentsStrategy = condimentsStrategy;}// 模板方法,定义咖啡的制作步骤final void makeCoffee() {boilWater();brewCoffeeGrounds();pourInCup();addCondiments();}// 具体步骤,煮沸水void boilWater() {System.out.println("Boiling water");}// 具体步骤,冲泡咖啡void brewCoffeeGrounds() {System.out.println("Brewing coffee grounds");}// 具体步骤,倒入杯中void pourInCup() {System.out.println("Pouring into cup");}// 具体步骤,添加调料,通过策略对象调用void addCondiments() {if (condimentsStrategy != null) {condimentsStrategy.addCondiments();}}
}// 具体子类,制作茶
class TeaTemplate extends CoffeeTemplate {// 构造方法中设置具体的调料策略TeaTemplate() {setCondimentsStrategy(new LemonCondiments());}
}// 具体子类,制作咖啡
class CoffeeTemplateImpl extends CoffeeTemplate {// 构造方法中设置具体的调料策略CoffeeTemplateImpl() {setCondimentsStrategy(new SugarAndMilkCondiments());}
}// 客户端代码
public class Client {public static void main(String[] args) {CoffeeTemplate tea = new TeaTemplate();tea.makeCoffee();CoffeeTemplate coffee = new CoffeeTemplateImpl();coffee.makeCoffee();}
}
// 引入 CondimentsStrategy 策略接口和具体的策略实现类:LemonCondiments 和 SugarAndMilkCondiments
// 如此将调料的添加变成一个可变的部分。在 CoffeeTemplateImpl 中引入策略对象,通过
// setCondimentsStrategy 设置具体的调料策略
  1. 分解大方法:如果模版方法变得复杂,考虑将其分解成多个小方法,使得每个方法都相对简单。
// 模板类
abstract class CoffeeTemplate {// 策略对象,用于调料的添加private CondimentsStrategy condimentsStrategy;// 设置调料策略void setCondimentsStrategy(CondimentsStrategy condimentsStrategy) {this.condimentsStrategy = condimentsStrategy;}// 模板方法,定义咖啡的制作步骤final void makeCoffee() {boilWater();brewCoffeeGrounds();pourInCup();addCondiments();}// 具体步骤,煮沸水void boilWater() {System.out.println("Boiling water");}// 具体步骤,冲泡咖啡void brewCoffeeGrounds() {System.out.println("Brewing coffee grounds");}// 具体步骤,倒入杯中void pourInCup() {System.out.println("Pouring into cup");}// 具体步骤,添加调料,通过策略对象调用void addCondiments() {if (condimentsStrategy != null) {condimentsStrategy.addCondiments();}}
}// 具体子类,制作茶
class TeaTemplate extends CoffeeTemplate {// 构造方法中设置具体的调料策略TeaTemplate() {setCondimentsStrategy(new LemonCondiments());}// 具体步骤,添加茶叶void addTeaLeaves() {System.out.println("Adding tea leaves");}
}// 具体子类,制作咖啡
class CoffeeTemplateImpl extends CoffeeTemplate {// 构造方法中设置具体的调料策略CoffeeTemplateImpl() {setCondimentsStrategy(new SugarAndMilkCondiments());}// 具体步骤,添加咖啡粉void addCoffeePowder() {System.out.println("Adding coffee powder");}
}// 客户端代码
public class Client {public static void main(String[] args) {TeaTemplate tea = new TeaTemplate();tea.makeCoffee();tea.addTeaLeaves();CoffeeTemplateImpl coffee = new CoffeeTemplateImpl();coffee.makeCoffee();coffee.addCoffeePowder();}
}

迭代器模式 Iterator

1、什么是迭代器模式

迭代器模式定义了一种方法来顺序访问一个容器对象中的各个元素,而不需要暴露该对象的内部细节,把对元素的访问和遍历从容器对象中分离出来,使得容器和迭代器可以独立地变化。

2、为什么使用迭代器模式

  1. 分离集合与遍历:迭代器模式将集合对象的遍历行为封装到迭代器中,使得集合与遍历的关注点分离。
  2. 简化集合接口:迭代器提供了一个统一的遍历接口,简化了集合类的接口,使得集合的实现更加简洁。
  3. 支持多种遍历方法:通过不同的迭代器实现,可以支持不同的遍历方法,比如正序、逆序、过滤等。

3、如何使用迭代器模式

设计实现一个集合类来实现迭代器模式

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;// 迭代器接口
interface MyIterator {boolean hasNext();Object next();
}// 集合接口
interface MyCollection {MyIterator createIterator();
}// 具体迭代器实现
class MyListIterator implements MyIterator {private List<Object> list;private int index = 0;MyListIterator(List<Object> list) {this.list = list;}@Overridepublic boolean hasNext() {return index < list.size();}@Overridepublic Object next() {if (hasNext()) {return list.get(index++);}return null;}
}// 具体集合实现
class MyListCollection implements MyCollection {private List<Object> list = new ArrayList<>();// 添加元素void addElement(Object element) {list.add(element);}// 创建迭代器@Overridepublic MyIterator createIterator() {return new MyListIterator(list);}
}// 客户端代码
public class Client {public static void main(String[] args) {MyListCollection collection = new MyListCollection();collection.addElement("Element 1");collection.addElement("Element 2");collection.addElement("Element 3");// 使用迭代器遍历集合MyIterator iterator = collection.createIterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}

4、是否存在缺陷和不足

迭代器模式不适用于所有的集合,主要是集合内部结构不方便直接使用迭代器的场景。

5、如何缓解缺陷和不足

  1. 使用增强的 for 循环:对于一些简单的集合,可以使用增强的 for 循环替代迭代器,代码更加简洁。
  2. 考虑其他遍历方式:如果迭代器不适用于某些集合,可以考虑其他遍历方式,比如通过索引访问元素。

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

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

相关文章

搭建知识付费平台?明理信息科技为你提供全程解决方案

明理信息科技saas知识付费平台 在当今数字化时代&#xff0c;知识付费已经成为一种趋势&#xff0c;越来越多的人愿意为有价值的知识付费。然而&#xff0c;公共知识付费平台虽然内容丰富&#xff0c;但难以满足个人或企业个性化的需求和品牌打造。同时&#xff0c;开发和维护…

【容器Docker】Docker学习笔记

1、什么是Docker&#xff1a; Docker 将程序和程序运行所依赖的所有环境都打包到镜像里。“build once, run anywhere”Docker 是容器的一种实现。 Windows 下如何安装Docker: 官方安装教程&#xff1a;Install Docker Desktop on Windows | Docker Docs有两种安装套装&…

使用openMVS库,在VS2022中启用c++17标准编译仍然报错

使用openMVS库&#xff0c;在VS2022中启用c17标准编译仍然报错 现象 项目中引用了某些开源库&#xff08;例如openmvs2.1.0&#xff09;&#xff0c;编译时要求启用编译器对c17的支持。 没问题&#xff01;大家都知道在下图所示的位置调整C语言标准&#xff1a; 但是&#…

智能优化算法应用:基于类电磁机制算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于类电磁机制算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于类电磁机制算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.类电磁机制算法4.实验参数设定5.算法…

ArcGIS Pro中去除黑边方法汇总

在有些时候&#xff08;比如镶嵌栅格后&#xff09;&#xff0c;我们获取到的影像数据可能会有黑边&#xff0c;这里为大家汇总一下在ArcGIS Pro中去除黑边的方法&#xff0c;希望能对你有所帮助。 数据来源 本教程所使用的数据是从水经微图中下载的影像数据&#xff0c;除了…

vmware离线安装docker-compose

vmware离线安装docker-compose 最近安装docker-compose&#xff0c;发现git取拉取&#xff0c;不是拒绝连接就是报443错误&#xff0c;或者其他错误 最后发现用包直接传上去好用&#xff0c;不用git拉取了 离线安装docker-compose 本文章给的docker-compose离线包&#xff0c;…

JNDI注入Log4jFastJson白盒审计不回显处理

目录 0x00 前言 0x01 Maven 仓库及配置 0x02 JNDI 注入简介 0x03 Java-第三方组件-Log4J&JNDI 0x04 Java-第三方组件-FastJson&反射 0x05 白盒审计 - FastJson 0x06 白盒审计 - Log4j 0x07 不回显的处理方法 0x00 前言 希望和各位大佬一起学习&#xff0c;如果…

多线程面试题

文章目录 1. 如何停止正在运行的线程2. 请你谈谈JMM&#xff08;java内存模型&#xff09;3. AQS4. ReentrantLock实现原理5. 死锁怎么检测 1. 如何停止正在运行的线程 设置一个共享变量作为线程退出的标记&#xff0c;当这个标记不满足时while循环&#xff0c;线程一直运行&a…

uniapp图片上传说明

目录 1.文件上传组件 2.单文件上传 3.多文件上传 4.注意点 1.文件上传组件 前端上传组件使用uni-file-picker&#xff0c;可以自行进行下载使用。默认上传到绑定的服务空间&#xff0c;配置属性auto-upload为false关闭自动上传&#xff0c;可以限定上传的是图片还是文件&am…

Databend 开源周报第 124 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 新增对 Delta 和…

使用Python编写简单网络爬虫实例:爬取图片

&#x1f34e;个人主页 &#x1f3c6;个人专栏&#xff1a;日常聊聊 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 ​编辑 简介 步骤 1. 安装依赖库 2. 创建目录 3. 发送HTTP请求并解析页面 4. 查找图片标签并下载图片 注意事项 结语 我的其他博客 简介 网络爬虫是一种…

等保测评主要保护哪些方面的安全?

等保测评是经公安部认证的具有资质的测评机构&#xff0c;依据国家信息安全等级保护规范规定&#xff0c;受有关单位委托&#xff0c;按照有关管理规范和技术标准&#xff0c;对信息系统安全等级保护状况进行检测评估的活动。那么企业做等保“保”的是什么呢&#xff1f; 等保主…

(自适应手机版)全屏滚动装修装潢公司网站模板

(自适应手机版)全屏滚动装修装潢公司网站模板 PbootCMS内核开发的网站模板&#xff0c;该模板适用于装修公司网站、装潢公司网站类等企业&#xff0c;当然其他行业也可以做&#xff0c;只需要把文字图片换成其他行业的即可&#xff1b; 自适应手机版&#xff0c;同一个后台&a…

SQL Server 安装教程

安装数据库 1、启动SQL Server2014安装程序&#xff0c;运行setup.exe文件&#xff0c;打开”SQL Server安装中心“对话框&#xff0c;单击左侧 的导航区域中的”安装“选项卡。 2、选择”全新SQL Server独立安装或向现有安装添加功能“&#xff0c;启动SQL Server2014安装向导…

自动驾驶技术入门平台分享:百度Apollo开放平台9.0全方位升级

目录 平台全方位的升级 全新的架构 工具服务 应用软件&#xff08;场景应用&#xff09; 软件核心 硬件设备 更强的算法能力 9.0版本算法升级总结 更易用的工程框架 Apollo开放平台9.0版本的技术升级为开发者提供了许多显著的好处&#xff0c;特别是对于深度开发需求…

LVS+Keepalived 高可用集群

一.Keepalived工具介绍 1.支持故障自动切换(Failover) 2.支持节点健康状态检查(Health Checking) 3.基于vrrp协议完成地址流动 4.为vip地址所在的节点生成ipvs规则(在配置文件中预先定义) 5.为ipvs集群的各RS做健康状态检测 6.基于脚本调用接口完成脚本中定义的功能&…

MyBatis ${}和#{}区别

sql防注入底层jdbc类型转换当简单类型参数$不防止Statment不转换value#防止preparedStatement转换任意 除模糊匹配外&#xff0c;杜绝使用${} MyBatis教程&#xff0c;大家可以借鉴 MyBatis 教程_w3cschoolMyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。…

RPC(5):AJAX跨域请求处理

接上一篇RPC&#xff08;4&#xff09;&#xff1a;HttpClient实现RPC之POST请求进行修改。 1 修改客户端项目 1.1 修改maven文件 修改后配置文件如下&#xff1a; <dependencyManagement><dependencies><dependency><groupId>org.springframework.b…

数据智慧:如何利用可视化提升效率

数据可视化是一项强大的工具&#xff0c;能够显著提高工作效率和决策的准确性。下面我就以可视化从业者的角度&#xff0c;简单谈谈数据可视化是如何助力效率提升的。 直观理解复杂数据 数据可视化将抽象的数据转化为图表、图形或仪表盘&#xff0c;使数据更易于理解。这种直观…

Linux系统之部署Linux管理面板1Panel

一、介绍 1.1简介 1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。 1.2特点 快速建站&#xff1a;深度集成 Wordpress 和 Halo&#xff0c;域名绑定、SSL 证书配置等一键搞定&#xff1b; 高效管理&#xff1a;通过 Web 端轻松管理 Linux 服务器&#xff0c;包括应用管…