深度对比简单工厂模式和策略模式
简单工厂模式 vs 策略模式UML看着像核心职责、使用场景、目的完全不同一、先纠正你的直观错觉UML结构只是类组成相似但角色分工、依赖方向、解决问题天差地别先统一两套模式标准UML角色再对比差异。1. 两套模式标准UML角色拆解1简单工厂模式静态工厂角色构成抽象产品 Product所有产品统一抽象接口比如Operation加减乘除运算具体产品 ConcreteProductA/B/C实现抽象产品的具体类Add、Sub、Mul工厂 Factory核心唯一创建者提供静态方法createProduct(type)根据参数判断new 对应具体产品实例返回抽象产品。客户端 Client只依赖「工厂」「抽象产品」不直接new具体产品客户端把创建参数传给工厂由工厂全权负责实例创建。UML关系Factory → 依赖 ProductFactory 实例化 ConcreteProductClient → 依赖 Factory Product核心动作工厂负责「对象创建」。2策略模式角色构成抽象策略 Strategy统一算法接口比如PayStrategy支付微信/支付宝/银行卡具体策略 ConcreteStrategyA/B/C实现抽象策略写不同算法逻辑WechatPay、AliPay上下文 Context核心持有一个Strategy成员变量对外提供业务方法execute()内部调用策略的算法提供setStrategy()动态切换策略。客户端 Client自己new具体策略实例传给Context客户端自主选择要使用的策略。UML关系Context 聚合 Strategy持有引用Client → 依赖 Context Strategy核心动作上下文负责「使用算法/执行业务」策略只封装可变算法。二、最核心4点本质区别重点区别1设计目标、解决的问题完全不同简单工厂解决「对象创建复杂」的问题痛点产品种类多、创建逻辑复杂、创建参数耦合在业务代码里不想让客户端到处new XXX()。核心职责封装实例化过程统一对象创建入口。关注点怎么造对象变化点新增产品时只改工厂的if/switch判断分支违反开闭原则这也是简单工厂不属于GOF23设计模式的原因策略模式解决「算法/业务逻辑频繁变化、大量if-else业务分支」的问题痛点同一个业务流程多种可替换算法大量if-else嵌套在业务类中难以维护、扩展。核心职责把可变算法抽离独立类实现算法与业务解耦动态切换。关注点怎么使用对象、运行时切换行为变化点新增算法只需要新增ConcreteStrategy完全不用改Context符合开闭原则区别2核心主控角色完全不一样简单工厂核心 工厂类 Factory所有实例创建逻辑全部收拢在工厂工厂是整个流程的控制中心客户端只告诉工厂“我要什么类型”创建过程完全交给工厂客户端不参与new具体类。示例客户端传typeadd工厂内部new Add()返回给客户端。策略模式核心 上下文 ContextContext是业务载体负责串联固定业务流程策略只是一段可替换的逻辑。客户端自己创建具体策略注入ContextContext只负责调用策略不负责创建策略。示例客户端ctx new OrderContext(); ctx.setStrategy(new WechatPay()); ctx.pay();区别3客户端权责、实例创建权归属不同简单工厂客户端不创建具体对象工厂全权创建// 简单工厂客户端代码OperationopOperationFactory.createOperation();// 客户端只传标识不new Addintresop.calc(1,2);客户端只持有抽象产品完全不感知具体产品类实例创建逻辑被屏蔽在工厂内部。策略模式客户端必须手动创建具体策略注入上下文// 策略模式客户端代码PayStrategypaynewWechatPay();// 客户端自己new具体策略OrderContextctxnewOrderContext(pay);ctx.doPay(99);// 运行时动态切换ctx.setStrategy(newAliPay());客户端明确知道自己要用哪一个具体策略Context不会主动创建策略只负责持有、调用策略。区别4开闭原则支持度、扩展代价不同简单工厂不满足开闭原则新增一个产品必须修改工厂里的分支判断if/switch修改原有代码会引入bug风险。例新增除法Div要去OperationFactory加case / : return new Div()。策略模式完美满足开闭原则新增算法只新增一个ConcreteStrategy实现类Context、原有策略完全不用修改无侵入。例新增数字人民币支付新建DigitalRMBPay实现PayStrategy上下文一行不用改。三、举同场景对比示例直观感受差异场景计算器支持加减乘除四种运算方案A用简单工厂实现抽象产品Operation提供calc(int a,int b)具体产品Add、Sub、Mul、Div工厂OperationFactory静态方法根据符号返回运算实例客户端只传符号由工厂创建运算对象执行计算重心怎么把加减乘除的new操作统一管理起来避免业务代码到处new。方案B用策略模式实现抽象策略CalcStrategy提供calc(int a,int b)具体策略AddStrategy、SubStrategy…上下文CalcContext持有CalcStrategy提供execute()执行计算客户端手动new AddStrategy传给CalcContext调用execute随时替换策略重心计算是固定业务流程加减乘除是可变算法做到运行时切换算法、解耦业务和计算逻辑。四、为什么UML图看起来几乎一样表层相似点只有2个都存在「抽象父接口 多个具体实现类」的分层都有一个中间类工厂/上下文依赖顶层抽象接口。但底层本质完全相反中间类的职责不同工厂造对象上下文用对象实例创建主体不同工厂内部new vs 客户端外部new设计目的不同封装创建逻辑 vs 封装可变算法扩展特性不同违反开闭 vs 遵循开闭。五、快速选择判断口诀如果你想统一管理对象的创建过程屏蔽复杂new逻辑 → 简单工厂如果你有同一套业务流程、多种可替换算法想消除大量if-else、运行时切换逻辑 → 策略模式如果你既要动态切换算法又不想客户端手动new策略 → 可以策略简单工厂组合使用工厂负责创建策略注入Context。六、补充组合使用案例解决策略模式客户端要new的痛点把简单工厂嵌入策略模式工厂负责创建策略客户端只传标识既拥有开闭特性又屏蔽创建逻辑// 工厂创建策略PayStrategystrategyStrategyFactory.getStrategy(wechat);OrderContextctxnewOrderContext(strategy);ctx.doPay();此时策略模式负责解耦业务与支付算法简单工厂负责屏蔽策略实例的创建细节二者各司其职互不冲突。C 策略模式完整实战示例业务场景商场收银系统3种优惠算法可动态切换正常原价收费打折如8折满减满300减100同一套收银流程优惠算法可运行时替换完美契合策略模式。模式角色对应抽象策略 StrategyCashStrategy统一收费算法接口具体策略 ConcreteStrategy正常收费/打折/满减各自实现计费逻辑上下文 ContextCashContext持有策略对象对外提供统一收银接口负责执行算法客户端 Client选择策略、传入上下文、执行计费#includeiostream#includememory// 1. 抽象策略类收费算法接口 classCashStrategy{public:virtual~CashStrategy()default;// 接收原价返回实际收款金额virtualdoubleacceptCash(doublemoney)const0;};// 2. 具体策略实现类 // 策略1正常收费无优惠classCashNormal:publicCashStrategy{public:doubleacceptCash(doublemoney)constoverride{returnmoney;}};// 策略2打折收费构造传入折扣0.88折classCashRebate:publicCashStrategy{private:doublerebate;public:explicitCashRebate(doubler):rebate(r){}doubleacceptCash(doublemoney)constoverride{returnmoney*rebate;}};// 策略3满减收费满condition减reduceclassCashReturn:publicCashStrategy{private:doublecondition;// 满多少doublereduce;// 减多少public:CashReturn(doublecond,doublered):condition(cond),reduce(red){}doubleacceptCash(doublemoney)constoverride{if(moneycondition){// 支持多次满减如满300减100600减200doubletimesmoney/condition;returnmoney-times*reduce;}returnmoney;}};// 3. 上下文 Context收银上下文 // 核心持有策略对象封装固定收银流程对外屏蔽算法细节classCashContext{private:std::unique_ptrCashStrategystrategy;// 持有策略聚合关系public:// 构造注入策略explicitCashContext(std::unique_ptrCashStrategys):strategy(std::move(s)){}// 运行时动态切换策略voidsetStrategy(std::unique_ptrCashStrategys){strategystd::move(s);}// 统一对外收银接口内部调用策略算法doublegetResult(doublemoney)const{returnstrategy-acceptCash(money);}};// 4. 客户端测试代码 intmain(){doubleoriginMoney1000;// 商品原价1000元std::cout 1. 使用原价策略 std::endl;CashContextctx1(std::make_uniqueCashNormal());std::cout应付金额ctx1.getResult(originMoney)std::endl;std::cout\n 2. 使用8折优惠策略 std::endl;CashContextctx2(std::make_uniqueCashRebate(0.8));std::cout应付金额ctx2.getResult(originMoney)std::endl;std::cout\n 3. 使用满300减100策略 std::endl;CashContextctx3(std::make_uniqueCashReturn(300,100));std::cout应付金额ctx3.getResult(originMoney)std::endl;std::cout\n 4. 运行时动态切换策略原价 → 5折 std::endl;CashContextctx4(std::make_uniqueCashNormal());std::cout切换前ctx4.getResult(originMoney)std::endl;// 动态替换算法无需修改上下文代码ctx4.setStrategy(std::make_uniqueCashRebate(0.5));std::cout切换后ctx4.getResult(originMoney)std::endl;return0;}输出结果 1. 使用原价策略 应付金额1000 2. 使用8折优惠策略 应付金额800 3. 使用满300减100策略 应付金额700 4. 运行时动态切换策略原价 → 5折 切换前1000 切换后500核心特性解读对应策略模式本质算法与业务解耦计费优惠逻辑全部抽离为独立策略类收银上下文CashContext只关心“收钱”这个固定业务不关心优惠怎么算。运行时动态切换setStrategy()可以在程序运行中替换算法不需要新建上下文对象。符合开闭原则新增优惠活动比如满赠、积分抵扣只需要新建CashStrategy派生类不用修改Context和原有策略代码。UML关系说明CashContext聚合CashStrategy持有指针/智能指针多个具体类继承抽象策略客户端创建具体策略注入上下文上下文不负责创建策略和简单工厂最核心区别和简单工厂的关键区分结合这段代码策略模式客户端自己make_uniqueCashRebate(0.8)创建策略上下文只使用、不生产对象简单工厂会单独写CashFactory客户端只传字符串rebate工厂内部new CashRebate屏蔽创建细节组合使用方案可以新增工厂类封装策略的创建解决客户端手动new策略繁琐的问题。拓展策略简单工厂 混合改造简化客户端新增工厂客户端不用手动new各种策略只传类型标识classCashStrategyFactory{public:staticstd::unique_ptrCashStrategycreateStrategy(conststd::stringtype){if(typenormal)returnstd::make_uniqueCashNormal();elseif(typerebate8)returnstd::make_uniqueCashRebate(0.8);elseif(typereturn300_100)returnstd::make_uniqueCashReturn(300,100);elsereturnstd::make_uniqueCashNormal();}};// 客户端简化写法CashContextctx(CashStrategyFactory::createStrategy(rebate8));C 简单工厂模式完整示例业务场景四则计算器加减乘除运算由工厂统一创建运算对象客户端只传运算符不手动 new 具体运算类。模式角色抽象产品 ProductOperation运算基类定义计算接口具体产品 ConcreteProductAdd、Sub、Mul、Div加减乘除工厂 FactoryOperationFactory静态方法根据标识创建对应运算实例客户端 Client只依赖工厂抽象产品屏蔽所有创建细节#includeiostream#includememory// 1. 抽象产品运算基类 classOperation{public:virtual~Operation()default;virtualdoublecalc(doublea,doubleb)const0;};// 2. 具体产品四则运算 // 加法classAdd:publicOperation{public:doublecalc(doublea,doubleb)constoverride{returnab;}};// 减法classSub:publicOperation{public:doublecalc(doublea,doubleb)constoverride{returna-b;}};// 乘法classMul:publicOperation{public:doublecalc(doublea,doubleb)constoverride{returna*b;}};// 除法classDiv:publicOperation{public:doublecalc(doublea,doubleb)constoverride{if(b0){std::cerr除数不能为0std::endl;return0;}returna/b;}};// 3. 简单工厂负责创建运算对象 classOperationFactory{public:// 静态工厂方法根据运算符创建对应运算实例staticstd::unique_ptrOperationcreateOperation(charop){switch(op){case:returnstd::make_uniqueAdd();case-:returnstd::make_uniqueSub();case*:returnstd::make_uniqueMul();case/:returnstd::make_uniqueDiv();default:std::cerr不支持的运算符std::endl;returnnullptr;}}};// 4. 客户端调用 intmain(){doublenum110,num22;// 客户端只传入运算符完全不用 new Add/Sub/Mul/DivautoopAddOperationFactory::createOperation();std::cout10 2 opAdd-calc(num1,num2)std::endl;autoopSubOperationFactory::createOperation(-);std::cout10 - 2 opSub-calc(num1,num2)std::endl;autoopMulOperationFactory::createOperation(*);std::cout10 * 2 opMul-calc(num1,num2)std::endl;autoopDivOperationFactory::createOperation(/);std::cout10 / 2 opDiv-calc(num1,num2)std::endl;return0;}运行输出10 2 12 10 - 2 8 10 * 2 20 10 / 2 5核心特点简单工厂标志性特征创建逻辑全部收拢在工厂所有new操作都在createOperation内部客户端看不到具体子类违反开闭原则如果新增「取余%」运算必须修改工厂里的switch分支改动原有代码工厂是唯一创建入口客户端只能通过工厂获取对象无权直接实例化具体产品关注点对象创建只解决“如何生产对象”不负责对象的业务执行。和之前策略模式的核心对比结合两份代码简单工厂工厂负责 new 对象客户端只拿抽象产品直接调用方法没有 Context 上下文策略模式客户端自己 new 策略对象注入 ContextContext 只使用策略绝不创建策略组合用法可以把简单工厂嵌入策略模式由工厂帮客户端创建策略简化调用。

相关新闻

从“自己搬砖”到“指挥别人搬砖”:DUSHMEM库如何让多卡通信更简单

从“自己搬砖”到“指挥别人搬砖”:DUSHMEM库如何让多卡通信更简单

如果你写过GPU程序,一定遇到过这样的场景:你手上有8块DCU,每块卡上都跑着一个进程(PE,Processing Element),你想让0号卡上的数据能被1号卡直接读取——怎么做? 最直接的办法是&#…

2026/7/9 1:14:42阅读更多 →
MoE 推理部署实战:同样的 6GB 显存,你选速度还是能力?

MoE 推理部署实战:同样的 6GB 显存,你选速度还是能力?

副标题: 三个模型、两组对比、一个三元 trade-off——MoE 在 6GB 家用卡上的真实表现 一、引子:纸上得来终觉浅 上一篇《大模型架构演进全景》从理论上梳理了 MoE 的设计思想:总参数大、激活参数小、每个 token 只走部分专家,用稀…

2026/7/9 1:14:42阅读更多 →
推荐太原多色美缝胶

推荐太原多色美缝胶

在家装翻新或新房装修中,美缝胶的选择往往是影响整体质感的关键细节。面对市场上琳琅满目的品牌和色彩,用户容易陷入“如何选色”、“哪种更耐黄变”、“哪里找靠谱施工团队”等困惑。针对太原本地用户,我们梳理了多色美缝胶的选购要点&#…

2026/7/9 1:14:42阅读更多 →
【ChatGPT vs DeepSeek终极对决】:20年AI架构师实测7大维度(推理速度、中文逻辑、代码生成、长上下文、幻觉率、API稳定性、企业级合规性)数据全公开

【ChatGPT vs DeepSeek终极对决】:20年AI架构师实测7大维度(推理速度、中文逻辑、代码生成、长上下文、幻觉率、API稳定性、企业级合规性)数据全公开

更多请点击: https://intelliparadigm.com 第一章:ChatGPT vs DeepSeek终极对决:一场面向生产环境的AI模型实测宣言 在真实业务场景中,模型选型不能依赖宣传口径或零散 benchmark,而必须经受高并发请求、长上下文推理…

2026/7/9 5:50:07阅读更多 →
最新搞定shopee虾皮数据采集

最新搞定shopee虾皮数据采集

Shopee(虾皮)是一个流行的东南亚电商平台,许多商家和开发者都对其商品详情数据感兴趣。为了采集Shopee上的商品详情数据,特别是根据商品ID获取商品详情,通常需要使用Shopee提供的 API接口 或者通过爬虫技术。然而&…

2026/7/9 5:50:07阅读更多 →
C++详细分析讲解引用的概念与使用

C++详细分析讲解引用的概念与使用

1.引用的概念引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。2.引用的格式类型 & 引用变量名 ( 对象名 ) 引用实体;举例如下:注意…

2026/7/9 5:50:07阅读更多 →
GPT-4 API 成本优化实战:3种调用策略对比,Token消耗降低40%

GPT-4 API 成本优化实战:3种调用策略对比,Token消耗降低40%

GPT-4 API成本优化实战:3种高效调用策略深度解析 当企业级应用开始规模化接入GPT-4 API时,开发者们往往会面临一个现实挑战——随着业务量增长,API调用成本呈现指数级上升。某电商平台在接入GPT-4生成商品描述后,仅一个月就产生了…

2026/7/9 5:50:07阅读更多 →
S7-200 SMART 存储卡应用:3分钟完成程序复制与密码清除操作

S7-200 SMART 存储卡应用:3分钟完成程序复制与密码清除操作

S7-200 SMART存储卡高效应用:程序批量部署与安全维护实战指南在工业自动化项目中,时间就是生产力。当面对数十台相同配置的PLC设备时,传统的一对一编程下载方式会消耗工程师大量时间。西门子S7-200 SMART系列PLC的MicroSD存储卡功能&#xff…

2026/7/9 5:50:07阅读更多 →
2026年,这家切削液净化专家如何让工厂废液变“黄金”?

2026年,这家切削液净化专家如何让工厂废液变“黄金”?

走进任何一家现代化的机加工车间,你都能听到机床运转的轰鸣声,看到冷却液(切削液)在设备与工件间奔流不息。这看似平常的工业血液,却隐藏着巨大的成本黑洞与环保风险:过滤不净导致工件报废、浮油滋生细菌引…

2026/7/9 5:45:07阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/8 5:12:14阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/8 7:00:12阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/9 2:47:07阅读更多 →
Three.js 着色器光效教程

Three.js 着色器光效教程

着色器光效 Shader Light ▶ 在线运行案例 案例合集: 三维可视化功能案例(threehub.cn)开源仓库github地址: https://github.com/z2586300277/three-cesium-examples400个案例代码: 网盘链接 你将学到什么 ShaderMaterial 自…

2026/7/9 0:04:37阅读更多 →
如何5分钟掌握CS2智能库存管理:开源工具CASEMOVE终极指南

如何5分钟掌握CS2智能库存管理:开源工具CASEMOVE终极指南

如何5分钟掌握CS2智能库存管理:开源工具CASEMOVE终极指南 【免费下载链接】casemove A dedicated desktop app that enables you to move items in and out of storage units in CS2. 项目地址: https://gitcode.com/gh_mirrors/ca/casemove 还在为CS2存储单…

2026/7/9 0:04:37阅读更多 →
GBase 8a vs MySQL 8.0:ALTER TABLE语法与限制的5点关键差异对比

GBase 8a vs MySQL 8.0:ALTER TABLE语法与限制的5点关键差异对比

GBase 8a与MySQL 8.0:ALTER TABLE语法差异深度解析与实战指南1. 两种数据库的ALTER TABLE能力全景对比在数据库架构设计和运维过程中,表结构变更(DDL操作)是不可避免的需求。GBase 8a作为国产分析型数据库代表,与开源M…

2026/7/9 0:04:37阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/8 6:59:54阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/8 13:42:39阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/8 13:42:39阅读更多 →