当前位置: 首页 > news >正文

Java 与设计模式(15):模板方法模式

一、定义

模板方法模式是一种行为设计模式,它定义了一个操作中的算法的骨架(也就是大致的步骤和流程),而将一些具体步骤的实现延迟到子类中。这样,子类可以不改变算法的结构即可重新定义算法的某些特定步骤。

二、Java示例

举个简单的例子:假设我们要泡一杯茶和一杯咖啡,这两者的制作过程有一些共同的步骤,比如烧水、倒水、搅拌等,但也有不同的地方,比如茶需要放茶叶,而咖啡需要放咖啡粉。

泡茶的过程:
烧水、放茶叶、倒水、搅拌、品尝
泡咖啡的过程:
烧水、放咖啡粉、倒水、搅拌、品尝

我们可以看到,烧水、倒水、搅拌和品尝这些步骤是相同的,而放茶叶和放咖啡粉这两个步骤是不同的。

用模板方法模式来实现:
我们可以定义一个抽象类 Beverage,它包含一个模板方法 prepareRecipe,这个方法定义了整个流程的骨架。然后,我们创建两个子类 Tea 和 Coffee,分别实现具体的步骤。

// 抽象类
abstract class Beverage {// 模板方法,定义算法骨架public final void prepareRecipe() {boilWater();brew();pourInCup();addCondiments();}// 抽象方法,由子类实现abstract void brew();// 抽象方法,由子类实现abstract void addCondiments();// 具体方法void boilWater() {System.out.println("烧水");}// 具体方法void pourInCup() {System.out.println("倒水到杯子里");}
}// 子类:茶
class Tea extends Beverage {@Overridevoid brew() {System.out.println("泡茶");}@Overridevoid addCondiments() {System.out.println("加糖");}
}// 子类:咖啡
class Coffee extends Beverage {@Overridevoid brew() {System.out.println("泡咖啡");}@Overridevoid addCondiments() {System.out.println("加牛奶");}
}// 测试代码
public class Main {public static void main(String[] args) {Beverage tea = new Tea();tea.prepareRecipe();System.out.println();Beverage coffee = new Coffee();coffee.prepareRecipe();}
}

输出结果:

烧水
泡茶
倒水到杯子里
加糖烧水
泡咖啡
倒水到杯子里
加牛奶

模板方法:prepareRecipe 是模板方法,它定义了整个流程的骨架,包括烧水、泡茶/咖啡、倒水、加调料等步骤。
抽象方法:brew 和 addCondiments 是抽象方法,由子类 Tea 和 Coffee 具体实现。
具体方法:boilWater 和 pourInCup 是具体方法,直接在抽象类中实现。

三、优点

  1. 代码复用性高
    优势:模板方法模式通过在抽象类中定义算法的骨架,将公共的代码逻辑集中到一个地方,避免了在多个子类中重复相同的代码。这样可以大大提高代码的复用性,减少代码冗余。
    示例:在订单处理系统中,无论是普通订单、VIP订单还是国际订单,它们的处理流程都包括接收订单、验证订单、支付处理、发货和通知客户等步骤。这些公共步骤可以在抽象类中实现,而具体的实现细节则由子类完成。
  2. 提高代码的可维护性
    优势:由于公共的代码逻辑集中在抽象类中,当需要修改这些公共逻辑时,只需在抽象类中进行修改,而不需要在每个子类中逐一修改。这大大减少了维护的复杂性和出错的概率。
    示例:如果需要在订单处理流程中增加一个新的步骤,如记录日志,只需在抽象类的模板方法中添加这一步骤,所有子类都会自动继承这一修改。
  3. 增强代码的可读性和可理解性
    优势:模板方法模式通过将算法的骨架和具体实现分离,使得代码结构更加清晰和有条理。这有助于开发者更好地理解系统的整体架构和各个部分的职责。
    示例:在泡茶和泡咖啡的例子中,Beverage 类定义了整个流程的骨架,而 Tea 和 Coffee 类则分别实现了具体的步骤。这种结构使得代码更加直观,易于理解和维护。
  4. 提高代码的灵活性和扩展性
    优势:模板方法模式允许子类在不改变算法骨架的前提下,通过重写抽象方法来实现特定的行为。这使得系统更加灵活,能够轻松应对需求的变化和扩展。
    示例:如果需要增加一种新的饮料,如奶茶,只需创建一个新的子类 MilkTea,并实现具体的泡制步骤,而不需要修改现有的代码。
  5. 约束子类的行为
    优势:通过在抽象类中定义抽象方法,模板方法模式可以强制子类实现这些方法,从而确保子类遵循一定的行为规范。这有助于避免子类的不一致实现,保证系统的稳定性和可靠性。
    示例:在订单处理系统中,抽象类可以定义 validateOrder 和 processPayment 等抽象方法,迫使子类实现这些方法,确保每个子类都按照规定的流程处理订单。
  6. 便于算法的替换和扩展
    优势:模板方法模式使得算法的骨架和具体实现分离,便于在不改变算法结构的情况下,通过继承和重写来替换或扩展算法的具体实现。
    示例:如果需要改变订单处理流程中的某个步骤,如支付处理方式,只需在相应的子类中重写 processPayment 方法,而不需要修改整个流程的骨架。
  7. 提高系统的可测试性
    优势:模板方法模式使得算法的骨架和具体实现分离,便于对算法的各个部分进行单独测试。这有助于提高系统的可测试性,确保每个部分都能正确工作。
    示例:可以单独测试 Beverage 类中的公共方法,如 boilWater 和 pourInCup,也可以单独测试 Tea 和 Coffee 类中的具体实现方法,如 brew 和 addCondiments。
  8. 促进代码的规范化和标准化
    优势:模板方法模式通过定义统一的算法骨架,促进了代码的规范化和标准化。这有助于团队协作和代码的统一管理,提高开发效率和代码质量。
    示例:在大型项目中,使用模板方法模式可以确保各个模块遵循统一的设计规范,减少因设计不一致导致的问题。

四、缺点

  1. 灵活性受限
    劣势:模板方法模式要求子类必须遵循父类定义的模板方法的结构,不能随意改变算法的骨架。这可能会限制子类的灵活性,使得子类在某些情况下难以实现特定的需求。
    示例:如果父类定义的模板方法中某个步骤的顺序或逻辑不符合子类的实际需求,子类无法直接修改模板方法的结构,只能通过重写抽象方法来实现特定的行为。这可能会导致代码的复杂性增加,或者需要通过其他方式来实现需求。
  2. 增加类的数量
    劣势:模板方法模式需要定义一个抽象类和多个子类,这会增加类的数量,从而增加系统的复杂性。在小型项目或简单场景中,这种增加的复杂性可能不值得。
    示例:如果一个简单的算法只需要几种不同的实现,使用模板方法模式可能会显得过于繁琐。相比之下,使用简单的条件语句(如 if-else 或 switch)可能更加简洁和高效。
  3. 维护成本增加
    劣势:由于模板方法模式涉及多个类和方法,维护和修改这些类的成本可能会增加。特别是当需要修改模板方法的结构时,可能需要同时修改多个子类,这会增加出错的概率和维护的难度。
    示例:如果需要在模板方法中添加一个新的步骤,不仅需要修改抽象类,还需要确保所有子类都能正确地实现这个新步骤。这可能会导致维护工作量增加,尤其是在子类数量较多的情况下。
  4. 代码的耦合性增加
    劣势:模板方法模式中,子类与抽象类之间的耦合性较高。如果抽象类中的方法或属性发生变化,可能会影响到所有子类的实现。这会增加系统的脆弱性,降低代码的可维护性。
    示例:如果抽象类中的某个方法被修改或删除,所有依赖该方法的子类都需要进行相应的修改。这可能会导致连锁反应,增加系统的维护难度。
  5. 学习和理解成本增加
    劣势:对于不熟悉模板方法模式的开发者来说,理解和学习这种模式可能需要一定的时间和精力。特别是在复杂的项目中,模板方法模式的使用可能会增加开发者的认知负担。
    示例:如果一个项目中大量使用了模板方法模式,新加入的开发者需要花费时间来理解这些模式的结构和实现,这可能会影响开发效率。
  6. 不适合频繁变化的场景
    劣势:如果算法的步骤或逻辑经常发生变化,使用模板方法模式可能会导致频繁的修改和维护。相比之下,使用其他设计模式(如策略模式)可能更加灵活和适应变化。
    示例:在快速迭代的项目中,如果算法的步骤经常需要调整,使用模板方法模式可能会导致频繁的类结构修改,增加开发和维护的成本。
  7. 可能导致代码的冗余
    劣势:虽然模板方法模式可以减少公共代码的重复,但在某些情况下,如果子类需要实现许多抽象方法,可能会导致代码的冗余。特别是当子类只需要少量的自定义行为时,这种冗余可能会更加明显。
    示例:如果一个子类只需要修改模板方法中的一个步骤,但仍然需要实现所有抽象方法,这可能会导致代码的冗余和不必要的复杂性。

五、使用场景

  1. 业务流程处理
    在业务系统中,许多业务流程具有固定的步骤,但某些步骤的具体实现可能因业务类型不同而有所差异。模板方法模式可以用来定义这些固定步骤的骨架,而将具体的实现留给子类。
    示例:
    订单处理流程:包括接收订单、验证订单、支付处理、发货、通知客户等步骤。这些步骤的顺序是固定的,但每个步骤的具体实现可能因订单类型(如普通订单、VIP订单、国际订单等)而不同。
    用户注册流程:包括输入信息、验证信息、发送验证码、注册成功等步骤。这些步骤的顺序是固定的,但每个步骤的具体实现可能因注册方式(如邮箱注册、手机号注册、第三方登录等)而不同。
  2. 算法框架
    在算法实现中,某些算法的步骤是固定的,但某些步骤的具体实现可能因具体问题而不同。模板方法模式可以用来定义算法的框架,而将具体的实现留给子类。
    示例:
    排序算法:许多排序算法(如冒泡排序、选择排序、插入排序等)的基本步骤是固定的,但具体的比较和交换操作可能不同。
    搜索算法:许多搜索算法(如深度优先搜索、广度优先搜索等)的基本步骤是固定的,但具体的搜索策略可能不同。
  3. 数据访问操作
    在数据访问层,许多数据操作(如插入、更新、删除、查询等)的基本步骤是固定的,但具体的实现可能因数据源(如数据库、文件、网络等)而不同。模板方法模式可以用来定义这些操作的框架,而将具体的实现留给子类。
    示例:
    数据库操作:包括连接数据库、执行SQL语句、处理结果集等步骤。这些步骤的顺序是固定的,但具体的实现可能因数据库类型(如MySQL、Oracle、SQL Server等)而不同。
    文件操作:包括打开文件、读取数据、写入数据、关闭文件等步骤。这些步骤的顺序是固定的,但具体的实现可能因文件类型(如文本文件、二进制文件、XML文件等)而不同。

六、注意事项

  1. 明确算法骨架
    注意:在使用模板方法模式时,必须明确算法的骨架,即整个流程的步骤和顺序。这需要在设计阶段仔细分析和规划,确保算法的骨架能够涵盖所有可能的实现。
    建议:在设计模板方法时,尽量将算法的骨架设计得通用和灵活,以便子类可以根据需要进行扩展和定制。
  2. 合理定义抽象方法
    注意:抽象方法是子类实现具体逻辑的地方,必须合理定义抽象方法的签名和职责。如果抽象方法定义得不合理,可能会导致子类实现困难或不一致。
    建议:抽象方法的签名应尽量简洁明了,职责单一,避免过于复杂或模糊的定义。同时,可以提供一些默认实现,减少子类的实现负担。
  3. 避免过度设计
    注意:模板方法模式可能会增加类的数量和复杂性,如果过度使用,可能会导致系统变得臃肿和难以维护。
    建议:在使用模板方法模式时,应根据实际需求进行权衡,避免过度设计。如果算法的步骤和逻辑相对简单,可以考虑使用其他更简单的设计模式或直接使用条件语句来实现。
  4. 确保子类的实现一致性
    注意:模板方法模式要求子类必须实现抽象方法,以确保算法的骨架能够正常运行。如果子类没有正确实现抽象方法,可能会导致算法无法正常执行。
    建议:在设计抽象类时,应提供清晰的文档和示例代码,指导子类如何正确实现抽象方法。同时,可以通过单元测试和代码审查来确保子类的实现一致性。
  5. 处理算法的变体
    注意:在某些情况下,算法的某些步骤可能会有多种变体,需要根据具体情况进行选择。如果这些变体没有得到妥善处理,可能会导致算法的灵活性和可扩展性受到影响。
    建议:可以通过增加抽象方法或使用其他设计模式(如策略模式)来处理算法的变体,提高算法的灵活性和可扩展性。
  6. 注意类的耦合性
    注意:模板方法模式中,子类与抽象类之间的耦合性较高。如果抽象类中的方法或属性发生变化,可能会影响到所有子类的实现。
    建议:在设计抽象类时,应尽量保持其稳定性,避免频繁修改。如果需要修改抽象类,应仔细评估对子类的影响,并及时通知相关开发者。
  7. 考虑性能影响
    注意:模板方法模式可能会增加方法调用的开销,特别是在算法步骤较多或调用频繁的情况下,可能会影响性能。
    建议:在性能敏感的场景中,应仔细评估模板方法模式的性能影响,必要时可以考虑优化算法或使用其他设计模式。
  8. 保持代码的可读性和可维护性
    注意:模板方法模式可能会增加代码的复杂性,如果代码结构不清晰,可能会导致可读性和可维护性下降。
    建议:在使用模板方法模式时,应保持代码结构清晰,注释详细,逻辑分明。可以通过合理的命名、分层和模块化来提高代码的可读性和可维护性。
  9. 避免滥用模板方法模式
    注意:模板方法模式并不是万能的,如果滥用可能会导致设计过于复杂,增加开发和维护的难度。
    建议:在使用模板方法模式时,应根据实际需求和场景进行选择,避免滥用。如果其他设计模式或简单的实现方式能够满足需求,应优先考虑。
  10. 结合其他设计模式使用
    注意:模板方法模式可以与其他设计模式(如策略模式、工厂方法模式等)结合使用,以提高系统的灵活性和可扩展性。
    建议:在设计系统时,可以根据实际需求和场景,灵活地结合使用多种设计模式,以达到最佳的设计效果。

七、在spring 中的应用

  1. JdbcTemplate
    JdbcTemplate 是 Spring 中用于简化 JDBC 操作的类,它使用了模板方法模式来封装 JDBC 的操作流程。JdbcTemplate 定义了整个 JDBC 操作的骨架,包括连接获取、SQL 执行、结果集处理等步骤,而具体的 SQL 语句和结果集处理逻辑由用户通过回调接口实现。
  2. AbstractController
    AbstractController 是 Spring MVC 中的一个抽象类,它使用了模板方法模式来定义控制器的处理流程。AbstractController 定义了 handleRequestInternal 方法作为模板方法,该方法定义了处理请求的骨架,而具体的请求处理逻辑由子类实现。

相关文章:

Java 与设计模式(15):模板方法模式

一、定义 模板方法模式是一种行为设计模式,它定义了一个操作中的算法的骨架(也就是大致的步骤和流程),而将一些具体步骤的实现延迟到子类中。这样,子类可以不改变算法的结构即可重新定义算法的某些特定步骤。 二、Ja…...

ubuntu更新失败:apt-get install -f Transaction failed: 软件包系统已损坏

检查您是否使用了第三方源。如果是就禁用它们,它们常常导致问题。 然后在终端中运行以下命令:apt-get install -f Transaction failed: 软件包系统已损坏下列软件包未满足的依赖关系:sunloginclient: Depends: libappindicator3-1 但是 %%s 没…...

16-使用QtChart创建动态图表:入门指南

QtChart是Qt框架中的一个强大模块,用于创建各种类型的图表,如折线图、柱状图、饼图等。它提供了丰富的API和灵活的配置选项,使得开发者能够轻松地将数据可视化集成到应用程序中。本文将介绍如何使用QtChart创建一个简单的动态折线图&#xff…...

C++ | 虚函数

在 C 面向对象编程领域,多态性堪称核心概念,而虚函数则是实现运行时多态的关键所在。 一、虚函数的概念与作用 1.1 什么是虚函数 虚函数是 C 中用于实现动态多态的成员函数。在基类中使用virtual关键字声明虚函数后,派生类能够重写&#x…...

单元测试整理

在国外软件开发中,单元测试必不可少,但是国内并不太重视这一块,一个好的单元测试可以提前发现很多问题,也减去和测试battle的时间 Spring单元测试 JUnit4 RunWith 指明单元测试框架 e.g. RunWith(SpringJUnit4ClassRunner.cla…...

Delphi语言的软件工程

Delphi语言的软件工程 引言 在软件工程的历史长河中,Delphi语言作为一种快速应用程序开发(RAD)的工具,凭借其高效的开发环境和强大的编程能力,一直在软件开发领域占有一席之地。本文将探讨Delphi语言的历史背景、特性…...

XSS攻击(跨站脚本攻击)详解与实战

文章目录 一、什么是XSS?二、XSS分类与场景三、XSS攻击实战流程四、CTF中的XSS利用五、XSS防御方案六、绕过过滤的常见技巧七、实战练习资源 一、什么是XSS? XSS(Cross-Site Scripting) 是一种通过向网页注入恶意脚本&#xff08…...

【C++指南】类和对象(十):const成员函数

💓 博客主页:倔强的石头的CSDN主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏:《C指南》 期待您的关注 目录 引言 一、const成员函数的定义与语法 1. 基本语法 2. 底层原理 二、const成员函数的作用与约束…...

数值分析与科学计算导引——误差与算法举例

文章目录 第一章 数值分析与科学计算导引1.1 数值分析的对象、作用与特点数值分析的对象数值分析的作用数值分析的特点 1.2 数值计算的误差误差分类误差与有效数字数值运算的误差估计 1.3 算法举例秦九韶算法求多项式值开根号迭代算法牛顿切线加权平均的松弛技术 第一章 数值分…...

ubuntu安装docker 无法拉取问题

sudo docker run hello-world [sudo] ubuntu 的密码: Unable to find image hello-world:latest locally docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": context deadline exceeded (Client.Timeout exceeded while awai…...

【C++项目】Rpc通信框架设计

目录 Rpc远程调用的思想 项目框架设计 服务端模块划分 网络通信模块 Network 应用层通信协议模块 Protocol 消息分发处理模块 Dispatcher 远程调用路由功能模块 RpcRouter ​编辑 发布订阅功能模块 Publish-Subscribe 服务注册/发现/上线/下线功能模块 Registry-Disc…...

八股取士--dockerk8s

一、Docker 基础 Docker 和虚拟机的区别是什么? 答案: 虚拟机(VM):虚拟化硬件,每个 VM 有独立操作系统,资源占用高,启动慢。Docker:容器化应用,共享宿主机内核…...

Autojs: 使用 SQLite

例子 let db new SQLiteUtil("/sdcard/A_My_DB/sqlite.db");db.fastCreateTable("user_table",{name: "",online: false,},["name"] // 设置 name 为唯一, 重复项 不会添加成功 );// 新增数据的 ID let row_id db.insert("use…...

思科、华为、H3C常用命令对照表

取消/关闭 思科no华为undo华三undo 查看 思科show华为display华三display 退出 思科exit华为quit华三quit 设备命名 思科hostname华为sysname华三sysname 进入全局模式 思科enable、config terminal华为system-view华三system-view 删除文件 思科delete华为delete华…...

解决 `pip is configured with locations that require TLS/SSL` 错误

问题描述 在使用 pip 安装 Python 包时,可能会遇到以下错误: WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.这意味着 Python 的 ssl 模块未正确安装或配置,导致 p…...

2025-arXiv-OmniThink:通过思考扩展机器写作的知识边界

arXiv | https://arxiv.org/abs/2501.09751 GitHub | https://github.com/zjunlp/OmniThink 项目主页 | https://zjunlp.github.io/project/OmniThink/ ModelScope 在线 Demo | https://www.modelscope.cn/studios/iic/OmniThink 摘要: 大语言模型驱动的机器写作通…...

【广州大学主办,发表有保障 | IEEE出版,稳定EI检索,往届见刊后快至1个月检索】第二届电气技术与自动化工程国际学术会议 (ETAE 2025)

第二届电气技术与自动化工程国际学术会议 (ETAE 2025) The 2nd International Conference on Electrical Technology and Automation Engineering 大会官网:http://www.icetae.com/【更多详情】 会议时间:2025年4月25-27日 会议地点&#xff1a…...

机器学习:01数学基础教程

函数 极限 按照一定次数排列的一列数:“,“,…,"…,其中u 叫做通项。 对于数列{Un}如果当n无限增大时,其通项无限接近于一个常数A,则称该数列以A为极限或称数列收敛于A,否则称数列为发散, 极限值 左…...

仿叮咚买菜鸿蒙原生APP

# DingdongShopping 这是一个原生鸿蒙版的仿叮咚买菜APP项目 鸿蒙Next发布至今已经有一年多的时间了,但有时候我们想要实现一些复杂的功能或者效果,在开发文档上查阅一些资料还是比较费时的,有可能还找不到我们想要的内容。而社会层面上分享…...

WordPress“更新失败,响应不是有效的JSON响应”问题的修复

在使用WordPress搭建网站时,许多人在编辑或更新文章时,可能会遇到一个提示框,显示“更新失败,响应不是有效的JSON响应”。这个提示信息对于不了解技术细节的用户来说,太难懂。其实,这个问题并不复杂&#x…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?

FTP&#xff08;File Transfer Protocol&#xff09;本身是一个基于 TCP 的协议&#xff0c;理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况&#xff0c;主要原因包括&#xff1a; ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...

【实施指南】Android客户端HTTPS双向认证实施指南

&#x1f510; 一、所需准备材料 证书文件&#xff08;6类核心文件&#xff09; 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...