南大复试 - 设计模式 📅 发布时间:2026/7/13 10:14:06 👁️ 浏览次数: 本文主要介绍南大软院复试中可能考察的几种设计模式。1、工厂模式该模式解决了什么问题 某个对象的创建和使用存在冗余代码可以封装创建逻辑解耦对象的创建和使用。- 引例 - 用户可以分别使用支付宝、微信的进行支付以及退款业务public class OrderService { // 1、该方法依据传入的 payType 选择不同的支付方式假设有支付宝和微信两种业务类型 public void payOrder(String orderId, double amount, String payType) { // ---------- tag ---------- // Payment payment null; if (alipay.equals(payType)) { Alipay alipay new Alipay(); // 假设初始化后需要传入用户 id 和用户密码 alipay.setAppId(alipay_123456); alipay.setPrivateKey(alipay_key_789); payment alipay; } else if (wechat.equals(payType)) { WechatPay wechatPay new WechatPay(); // 假设微信也有自己的初始化入参 wechatPay.setMchId(wechat_mch_001); wechatPay.setApiKey(wechat_key_002); payment wechatPay; } else { throw new RuntimeException(不支持的支付方式); } // ---------- tag ---------- // // 2、实例初始化后开始具体业务逻辑 // ………… // } }假设我们要做一个“支付”或是“退款”的业务有两种支付方式支付宝和微信那么业务调用的地方一般是传入一个 payType 根据不同字段选择支付宝和微信的跳转业务逻辑即注释 1。存在的问题1、初始化实例的过程中即上述两个注释 tag 中间的这段代码对于“支付”和“退款”也有可能有其他的业务业务这里的初始化信息一般是不变的。因此如果我们不使用工厂模式那对于“支付”和“退款”这两个方法上述两个 tag 之间的这段代码我们会在这两个方法中原封不动的写两遍。2、若业务需要增加了“银联”支付方式那么我们要在“支付”“退款”这两个方法中分别增加银联的冗余代码。接下来引入简单工厂模式解决这个问题// 1、将支付和退款定义成接口 public interface Payment { String pay(double amount); String refund(double amount); } // 2、抽出支付宝实现类和微信实现类这两个类分别实现支付和退款的业务接口 public class Alipay implements Payment { private String appId; private String privateKey; // 一些支付宝的初始化入参 public void setAppId(String appId) { this.appId appId; } public void setPrivateKey(String privateKey) { this.privateKey privateKey; } Override public String pay(double amount) { // 支付宝支付业务逻辑 } Override public String refund(double amount) { // 支付宝退款业务逻辑 } } public class WechatPay implements Payment { private String mchId; private String apiKey; public void setMchId(String mchId) { this.mchId mchId; } public void setApiKey(String apiKey) { this.apiKey apiKey; } Override public String pay(double amount) { // 微信支付业务逻辑 } Override public String refund(double amount) { // 微信退款业务逻辑 } } // 3、创建一个工厂类 public class PaymentFactory { public static Payment createPayment(String payType) { // 工厂根据传入的 payType 创建支付实例若有其他支付方式也只需在这里扩展 Payment payment switch (payType) { case alipay - new Alipay(); case wechat - new WechatPay(); default - throw new RuntimeException(不支持的支付方式 payType); }; // 统一初始化配置只要在工厂类中写一次支付、退款以及其他业务模块都能用 if (payment instanceof Alipay alipay) { alipay.setAppId(alipay_123456); alipay.setPrivateKey(alipay_key_789); } else if (payment instanceof WechatPay wechatPay) { wechatPay.setMchId(wechat_mch_001); wechatPay.setApiKey(wechat_key_002); } return payment; } } // 4、在原先的业务代码中使用工厂 public class OrderService { public void payOrder(String orderId, double amount, String payType) { // 实例化工厂 PaymentFactory factory new PaymentFactory() // 这里可以把工厂做成一个单例来使用 // 从工厂中获取对应的已经初始化完成的支付方式 Payment payment factory.createPayment(payType); // 支付、退款业务逻辑 // ………… // } }使用工厂模式后实现同样的功能虽然增加了代码行数但是模块之间耦合性降低了若要修改支付宝的初始化代码或是支付、退款逻辑只需在 Class Alipay 中修改若是要增加一个银联的支付方式只需增加一个 Class UnionPay在里面写它的初始化和支付退款业务逻辑业务调用的地方无需进行改动。扩展 - 工厂方法模式上述简单工厂模式如果需要增加银联支付则需要修改工厂类这违反了开闭原则。简单工厂是单工厂多产品的模式因此为防止工厂类随项目扩展变得臃肿我们可以使用多工厂多产品的结构也即是工厂方法模式。// 工厂接口 public interface PaymentFactory { Payment createPayment(); } // 支付宝工厂 public class AlipayFactory implements PaymentFactory { Override public Payment createPayment() { return new Alipay(); } }新增产品时就只需新增新工厂类和新产品类。对于简单工厂和工厂方法模式虽然工厂方法模式符合开闭原则但是代价是增加了代码复杂度不同的产品都需要一个独特工厂是一个混代码量的方法。。个人认为在实际开发中采用简单工厂写出来的代码更简洁易管理。简而言之工厂模式主要是用于封装对象的创建初始化数据代码。2、策略模式同样的首先思考策略模式是为了解决什么问题工厂模式是封装对象的创建代码而策略模式则是封装某个“过程”策略的代码使得策略若是有变更或是扩展时只需低成本改动便可与原业务兼容。- 引例 - 某电商订单折扣计算规则不使用策略模式时的代码如下// 订单类核心业务算法分支混在一起 public class Order { private String userId; private String userType; private double amount; // 计算折扣后金额if-else 臃肿且难扩展 public double calculatePayAmount() { double payAmount 0.0; if (普通用户.equals(userType)) { payAmount amount; } else if (VIP.equals(userType)) { payAmount amount * 0.9; } else if (超级VIP.equals(userType)) { payAmount amount * 0.8; } else if (节日活动.equals(userType)) { // 新增规则需改这里 payAmount amount * 0.85; } else { throw new IllegalArgumentException(未知用户类型); } return payAmount; } // getter/setter 省略 } // 客户端调用 public class Client { public static void main(String[] args) { Order order new Order(); order.setUserId(1001); order.setUserType(VIP); order.setAmount(1000.0); System.out.println(需支付 order.calculatePayAmount()); // 输出900.0 } }该写法存在以下问题1、新增 “节日活动” 折扣时必须修改calculatePayAmount()方法违反开闭原则。2、如果折扣规则调整比如 VIP 改成 8.8 折需要在if-else里找对应分支修改容易误改其他逻辑。3、折扣算法无法复用比如退款模块也需要计算折扣只能复制代码。接下来使用策略模式对这段代码进行修改// 1、定义策略接口定义所有折扣算法的统一方法 public interface DiscountStrategy { // 计算折扣后金额 double calculate(double amount); } // 2、定义不同策略实现该接口 // 普通用户策略 public class NormalUserStrategy implements DiscountStrategy { Override public double calculate(double amount) { return amount; } } // VIP用户策略9折 public class VipUserStrategy implements DiscountStrategy { Override public double calculate(double amount) { return amount * 0.9; } } // 超级VIP用户策略8折 public class SuperVipUserStrategy implements DiscountStrategy { Override public double calculate(double amount) { return amount * 0.8; } } // 节日活动策略8.5折—— 新增策略只需加类无需改旧代码 public class FestivalStrategy implements DiscountStrategy { Override public double calculate(double amount) { return amount * 0.85; } } // 3、定义上下文该类主要用于持有策略对象封装策略的调用逻辑 public class OrderContext { // 持有策略对象 private DiscountStrategy strategy; // 构造方法传入具体策略 public OrderContext(DiscountStrategy strategy) { this.strategy strategy; } // 对外提供的计算方法 public double calculatePayAmount(double amount) { return strategy.calculate(amount); } // 支持动态切换策略可灵活扩展 public void setStrategy(DiscountStrategy strategy) { this.strategy strategy; } } // 4、修改客户端调用逻辑 public class Client { public static void main(String[] args) { double orderAmount 1000.0; // 选择不同策略 DiscountStrategy vipStrategy new VipUserStrategy(); // context 持有该策略 OrderContext context new OrderContext(vipStrategy); // 使用策略计算金额 System.out.println(VIP用户需支付 context.calculatePayAmount(orderAmount)); // 900.0 // 可自由切换策略只需将其传入上下文 context.setStrategy(new FestivalStrategy()); // 使用节日策略计算金额 System.out.println(节日活动需支付 context.calculatePayAmount(orderAmount)); // 850.0 } }可以看出策略模式核心步骤如下1、定义该策略接口2、定义不同类实现该接口3、定义上下文用于持有策略4、客户端中直接实例化上下文以及需要的策略上下文持有策略后就可以使用该策略
PCB12层板排行榜 实测冠军揭晓 对于高速数字电路设计范畴来讲,存在这样一句话,即“8层属于入门级别,12层则是分水岭所在”。当信号的频率超越10Gbps这个数值的时候,当电源完整性方面的要求变得极为严格苛刻之际,当产品需要于极端的环境当中维持零故障… 2026/7/9 16:43:12
ElasticSearch快速入门实战(2)-相关性、多字段搜索优化(copy to)、聚合操作、自定义分词 【48、ElasticSearch搜索技术深入与聚合查询实战】4.12 什么是相关性相关性的概述:描述一个文档与查询语句匹配程度的衡量标准.ES有一个评分算法,根据查询条件与索引文档的匹配程度来计算相关性.评分算法:Okapi BM25(RAGFlow关键词搜索也有这个算法)4.14.1 Index Boost在索引层… 2026/7/10 17:15:48
【实时Linux工业PLC解决方案系列】第十二篇 - 实时Linux PLC EtherCAT主站实时方案 一、简介:为什么 EtherCAT 是工业实时通信的首选?EtherCAT 优势:百兆以太网物理层,单帧遍历全站,理论周期 31.25 μs。分布式时钟(DC)精度 < 100 ns,多轴同步无需额外硬件。开源主… 2026/7/9 6:40:37
《Java 100 天进阶之路》第55篇:线程池ThreadPoolExecutor(2026版) 第55篇:线程池ThreadPoolExecutor(2026版) 📌 系列导航:《Java 100 天进阶之路》完整目录 | ⬅️ 上一篇:第54篇:AQS抽象队列同步器 | ➡️ 下一篇:第56篇:死锁与排查工具… 2026/7/13 10:10:42
C++ STL核心容器std::string深度解析:从内存管理到实战应用 1. 项目概述:为什么说“不懂STL,就不会C”? 如果你正在学习C,或者已经用C写过一些代码,但总觉得自己的代码写起来又长又笨重,别人写的代码却简洁高效,那问题很可能就出在STL上。我见过太多初学者… 2026/7/13 10:10:42
高压安全隔离技术:ISOM8710与STM32F722ZE的工业应用 1. 高压安全隔离的基础原理与行业需求在工业自动化、电力电子和医疗设备等领域,高压安全隔离是确保系统可靠性和人员安全的关键技术。传统的光耦隔离方案存在老化快、传输速率低等固有缺陷,而基于电容隔离的ISOM8710芯片则代表了新一代解决方案。电容隔离… 2026/7/13 10:08:41
Unity移动端AssetBundle下FairyGUI与Spine材质丢失问题分析与解决方案 1. 项目概述:当FairyGUI遇上Spine,移动端资源管理的“暗礁” 在Unity移动端项目的UI与动画开发中,FairyGUI和Spine的组合堪称“黄金搭档”。FairyGUI以其高效的UI编辑器和运行时性能著称,而Spine则是2D骨骼动画领域的行业标准&… 2026/7/13 10:08:41
C++凯撒密码实现:模运算在循环移位中的核心应用与洛谷P1914题解 1. 项目概述与核心价值最近在洛谷上刷题,看到P1914这道“小书童——凯撒密码”的题目,感觉特别有意思。它表面上是一个简单的字符串处理题,但背后却藏着循环移位这个在密码学和数据处理中非常核心的概念。很多刚接触C和算法的朋友,… 2026/7/13 10:04:39
软件工程可行性分析实战:3个维度量化评估,避免项目“烂尾” 软件工程可行性分析实战:3个维度量化评估,避免项目“烂尾” 去年参与的一个企业级SaaS项目让我深刻体会到可行性分析的价值。团队在立项阶段花费两周时间完成的技术可行性矩阵,后来成功预警了三个关键风险点,其中关于第三方API调用… 2026/7/13 10:04:39
HS2-HF Patch终极指南:如何用3步解决Honey Select 2的70+个痛点 HS2-HF Patch终极指南:如何用3步解决Honey Select 2的70个痛点 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 你是否曾经在Honey Select 2中遇到过… 2026/7/13 0:01:19
语音转文字工具AsrTools:让音频整理变得简单高效 语音转文字工具AsrTools:让音频整理变得简单高效 【免费下载链接】AsrTools ✨ AsrTools: Smart Voice-to-Text Tool | Efficient Batch Processing | User-Friendly Interface | No GPU Required | Supports SRT/TXT Output | Turn your audio into accurate text … 2026/7/13 0:03:19
基于深度学习的蘑菇或花卉或动漫人物或中草药货水果蔬菜等识别系统31(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_ 基于深度学习的蘑菇或花卉或动漫人物或中草药货水果蔬菜等识别系统31(设计源文件万字报告讲解)(支持资料、图片参考_相关定制)_ 独家界面!不会重复,此项目属于本人原创,若有雷同,均是盗卖,各位买… 2026/7/13 0:05:20
Git reset 与 revert 深度对比:5个关键差异与 3 种典型应用场景 Git Reset 与 Revert 深度对比:5个关键差异与3种典型应用场景在团队协作开发中,代码版本管理如同行走钢丝——一步失误可能导致整个项目陷入混乱。作为Git进阶用户,你是否曾在深夜面对错误的提交束手无策?是否在强制推送后收到同事… 2026/7/13 8:31:55
GitHub 学生包申请避坑:5个常见失败原因与开发者工具调试方案 GitHub 学生包申请技术排障指南:5个高频失败场景与开发者工具实战方案第一次尝试申请GitHub学生包时,我盯着屏幕上那个不断转圈的加载动画整整15分钟,最终只等来了一行冰冷的错误提示。这可能是许多开发者共同的经历——明明按照教程操作&… 2026/7/13 9:31:08
冒烟测试用例设计规范:5%-10%覆盖率下的3类核心场景与执行标准 冒烟测试用例设计的黄金法则:5%-10%覆盖率下的精准筛选策略在快节奏的敏捷开发环境中,冒烟测试作为质量保障的第一道防线,其重要性不言而喻。当测试资源有限而时间紧迫时,如何从海量测试用例中精准筛选出那关键的5%-10%࿰… 2026/7/13 2:34:55