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

生产环境【设计模式】策略模式:可插拔算法,从硬编码到灵活适配,体会“算法解耦“思想最佳实践与性能优化

最近在做项目时深入研究了这个技术点,踩了不少坑,这里整理一份完整指南分享给大家。


请添加图片描述


半桔:个人主页

  个人专栏: 《设计模式》《手撕面试算法》《C++从入门到入土》

恐惧囚禁人的灵魂,希望可以让你自由。《肖申克的救赎》

文章目录

  • 一. 光头强转行
    • 1.1 团结屯的故事
    • 1.2 新工作,新需求
  • 二. 光头强的OO天赋
  • 三. 李老板的新需求
    • 3.1 出大问题了
    • 3.2 继承可能不是答案
  • 四. 最终方案
  • 五. 总结

一. 光头强转行

1.1 团结屯的故事

我是光头强。以前,我每天的生活就是被两头臭狗熊按在地上摩擦,不仅树砍不到,还要承受李老板的夺命连环Call和扣工资威胁。

直到有一天,我捡到了一本《C++ Primer》(虽然我也忘了森林里为啥会有这书)。那一刻,我悟了!砍树是没有前途的,计算机才是第一生产力

我狠下心来闭关修炼,左手C++,右手面向对象(OO),发际线虽然更高了(额,我好像也没什么头发),但我感觉自己强得可怕。于是,我把电锯一扔,拿起键盘,给李老板发了辞职信:“世界那么大,我想去敲代码。”

李老板一听我要走,顿时慌了:“强子!你走了,《熊出没》还怎么拍?这动画片没反派怎么行?这样,工资翻倍(虽然原来只有300),给你安排新岗位:首席架构师。你给我开发一个《狗熊模拟器》!”

为了那点窝囊费……啊不,为了展现我的技术。

1.2 新工作,新需求

项目需求文档 - 《狗熊模拟器 v1.0》
甲方:李老板
描述:模拟团结屯狗熊的习性。
功能点:冬眠、爬树、居住习惯,以及最喜欢的食物。

二. 光头强的OO天赋

看完需求,我嘴角上扬。这不就是典型的继承题吗? 既然熊大熊二都住在团结屯,除了吃的口味不同,其他行为(冬眠、爬树、住树洞)完全一致。 我决定使用继承大法,主打一个代码复用,少写一行是一行。

请添加图片描述

class Bear
{
public:
virtual std::string FavoriteFood() = 0;
void Hibernation() { std::cout << "进行冬眠" << std::endl; }
void ClimbTree() { std::cout << "会爬树" << std::endl; }
void LivingHabit() { std::cout << "住在树洞里面" << std::endl; }
protected:
};
class XiongDa : public Bear
{
public:
std::string FavoriteFood() override{ return "苹果"; }
};
class XiongEr : public Bear
{
public:
std::string FavoriteFood() override { return "蜂蜜"; }
};

代码行云流水,提交Git,李老板看后直呼内行。

三. 李老板的新需求

李老板发现这个程序很有商业价值,格局打开,要把业务扩展到全宇宙的森林,不只是团结屯。

3.1 出大问题了

新增需求:系统要支持北极熊、熊猫、甚至玩具熊。

优化建议:

如果你的项目访问量较大,建议增加缓存机制。我们团队在优化后,接口响应时间从800ms降到了50ms, 效果非常明显。具体的缓存策略可以根据业务场景调整。

这时候我才发现,刚刚为了偷懒把 HibernationClimbTree写死在基类里,简直是在给自己挖坑!

  • 北极熊:不冬眠啊!
  • 玩具熊:人家连活物都不是,爬个鬼的树!

如果继续用继承,我只能**覆盖基类的方法了:

请添加图片描述

为了适配新物种,我必须在每个子类里重写代码。

  • 如果有100种不冬眠的熊,我就要写100遍“不冬眠”的函数?

我希望通过继承的方式来达到代码复用的目的,但是涉及到维护时,效果并不是那么好,现在代码已经完全不能进行代码的复用了

3.2 继承可能不是答案

我痛定思痛,回想起那本C++圣经上的教诲:

设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

简单说就是:既然“怎么爬树”和“怎么冬眠”是会变的,那就把它们踢出 Bear 类,单独封装!
我要把“行为”变成一种“零件”,哪只熊需要什么零件,组装上去就行了。这就是组合
你决定将基类的方式实现进行封装起来,对代码进行重构。

现在,Bear 类不再亲自负责实现“爬树”这个动作,它只负责拥有一个“爬树行为”的接口。
具体怎么爬?让接口的实现类去操心吧!
请添加图片描述

四. 最终方案

为了代码整洁,我们专注于重构 HibernationClimbTree 这两个变化点。

  1. 先把“怎么冬眠”抽象成一个接口族:
class Hibernation_Behavior
{
public:
virtual void Hibernation() = 0;
};
class Hibernation_able : public Hibernation_Behavior
{
public:
void Hibernation() override { std::cout << "进行冬眠" << std::endl; }
};
class Hibernation_unable : public Hibernation_Behavior
{
public:
void Hibernation() override { std::cout << "不需要冬眠" << std::endl; }
};
  1. 同理,把爬树能力也拆分出来:
class ClimbTree_Behavior
{
public:
virtual void ClimbTree() = 0;
};
class ClimbTree_able : public ClimbTree_Behavior
{
public:
void ClimbTree() override { std::cout << "会爬树" << std::endl; }
};
class ClimbTree_unable : public ClimbTree_Behavior
{
public:
void ClimbTree() override { std::cout << "不需要爬树" << std::endl; }
};
  1. 重构 Bear 类
class Bear
{
public:
virtual void Hibernation() = 0;
virtual void ClimbTree() = 0;
protected:
std::shared_ptr<Hibernation_Behavior> hibernation_behavior_;std::shared_ptr<ClimbTree_Behavior> climbTree_behavior_;};
  1. 各种熊的实现:
class BrownBear : public Bear
{
public:
BrownBear()
{
hibernation_behavior_ = std::make_shared<Hibernation_unable>();climbTree_behavior_ = std::make_shared<ClimbTree_able>();}void Hibernation() { hibernation_behavior_->Hibernation(); }void ClimbTree() { climbTree_behavior_->ClimbTree(); }};class Panda : public Bear{public:Panda(){hibernation_behavior_ = std::make_shared<Hibernation_unable>();climbTree_behavior_ = std::make_shared<ClimbTree_able>();}void Hibernation() { hibernation_behavior_->Hibernation(); }void ClimbTree() { climbTree_behavior_->ClimbTree(); }};

五. 总结

这就是传说中的策略模式(Strategy Pattern)

通过把 Hibernation_BehaviorClimbTree_Behavior 定义为算法族,我们将行为的实现与使用行为的 Bear 类彻底解耦。

好处显而易见:

  1. 复用性起飞:如果不冬眠的代码逻辑变了,我只需要改 Hibernation_unable 这一个类,所有不冬眠的熊都会自动更新。
  2. 扩展性无敌:李老板要是让我加个“机械熊”,我只需要新写一个 RocketJump_Behavior,然后在机械熊里装配上就行,根本不用去动原来的代码。

最后策略模式定义就是: 定义算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

好了,代码写完了,李老板对此非常满意,决定再奖励我加班修Bug。我要去砍树…啊不,去Debug了,下期见!

http://www.jsqmd.com/news/382329/

相关文章:

  • 两种可行的技巧将 Outlook 联系人传输到三星手机
  • 唐山瑞途教育单招实力解析:师生认可与考评领先的靠谱之选 - 品牌排行榜单
  • 2026年口碑好的地上箱泵一体化/抗浮式箱泵一体化厂家采购参考指南(必看) - 行业平台推荐
  • 2026年质量好的医疗三维动画设计/工业三维动画销售厂家采购建议选哪家 - 行业平台推荐
  • 2026年靠谱的盐城一体化无浮泵站/一体化预制泵站高评分品牌推荐(畅销) - 行业平台推荐
  • 2025年十大调节阀品牌盘点,谁主沉浮?电动调节阀/气动调节阀/美标调节阀/自力式调节阀/气动高温调节阀/调节阀调节阀优质厂家哪里有卖 - 品牌推荐师
  • 2026年知名的高效机房设计/机房销售厂家推荐哪家好(真实参考) - 行业平台推荐
  • 完整教程:大数据Spark(七十六):Action行动算子reduce和take、takeSample使用案例
  • IDA Pro 9.3 正式版发布 - 强大的反汇编程序、反编译器和多功能调试器
  • 这一路破空 苦难有千重谁人懂 只求有朝再相逢
  • 2026年评价高的上海企业报销系统/自动报销系统精选推荐平台 - 行业平台推荐
  • 聚焦RTO供货商:2026年市场服务模式解析,旋风除尘器/滤筒除尘器/沸石转轮一体机/除尘器/沸石转轮,RTO厂家推荐榜 - 品牌推荐师
  • 2026年热门的横梁机床铸件/机床铸件底座口碑排行精选供应商推荐 - 行业平台推荐
  • 2026年靠谱的吉林数字人制作/长春数字人制作智能化推荐平台 - 行业平台推荐
  • 2026年口碑好的智慧操场/智慧操场跑步测试仪管理推荐厂家 - 行业平台推荐
  • 印刷糊箱联动线定制:2026年优质厂家应具备的特质,印刷糊箱联动线怎么选购精选国内优质品牌榜单 - 品牌推荐师
  • 30岁小白转行AI大模型?收藏这份学习路线,带你轻松入行!30岁转行AI大模型,刚好赶上风口!
  • 2026年质量好的供热聚氨酯保温管道/河北预制聚氨酯保温管真实参考销售厂家参考怎么选 - 行业平台推荐
  • 2026年热门的长春短视频运营/长春短视频运营代理商热门企业推荐公司 - 行业平台推荐
  • 2026年昆山交通事故律师推荐:2026年度昆山交通事故律师深度对比评测与口碑排名报告 - 资讯焦点
  • 2026年口碑好的金属抛光去毛刺机/不锈钢拉丝去毛刺机厂家推荐哪家好(高评价) - 行业平台推荐
  • 2026年国内热门的闸阀工厂排行榜,手动闸阀/铸钢截止阀/铸钢阀门/不锈钢止回阀/软密封闸阀,闸阀制造商哪家好 - 品牌推荐师
  • 2026年口碑好的兆声波晶圆清洗机厂家用户口碑推荐清单 - 品牌鉴赏师
  • 复分析初步:复数乘法
  • PingCastle Pro 3.5.0.7 - Active Directory 安全检测和评估
  • 2026年热门的专用机床铸件/铸铁机床铸件可靠供应商参考哪家靠谱(可靠) - 行业平台推荐
  • 2026年比较好的聚氨酯喷涂缠绕保温管/河北聚氨酯发泡保温管道源头厂家采购指南怎么选(畅销) - 行业平台推荐
  • 2026年评价高的河北蒸汽保温管道/钢套钢蒸汽保温管实力厂家推荐如何选 - 行业平台推荐
  • 2026年热门的天津二手集装箱装箱/天津二手集装箱租赁推荐几家可靠供应商参考 - 行业平台推荐
  • 2026年优秀的HIFU换能器厂家口碑品牌推荐榜 - 品牌鉴赏师