尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

设计模式速记指南:工厂、策略与组合模式的底层逻辑与应试要点

发布时间:2026/9/16 22:01:25

资讯中心
01
ARTICLE

设计模式速记指南:工厂、策略与组合模式的底层逻辑与应试要点

设计模式速记指南:工厂、策略与组合模式的底层逻辑与应试要点
设计模式这东西我敢打赌十个人里有八个是“背了忘、忘了背”的循环。尤其是期末考前突击、面试前临时翻书24种模式其实GoF经典是23种后来大家习惯把简单工厂也算进去凑成24看一遍下来脑子里只剩下“单例、工厂、观察者”三个词其他全糊了。我自己带过不少实习生也帮人改过大作业发现大家卡住的根本不是“模式本身难”而是没有找到一条能把模式串起来的主线——每个模式都是孤立的记忆点当然记不住。这篇东西就是冲着“速记”来的围绕简单工厂、工厂方法、抽象工厂、策略、组合这几个高频考点把底层逻辑拆开揉碎顺便把C和Java两派的实现差异、期末笔试的踩坑点、大作业的设计思路一起说透。正在被设计模式折磨的、马上要考试或面试的这篇应该能帮你省下不少时间。1. 先别急着背定义理解“变化”才是记忆的锚点先问个问题设计模式到底是干嘛的教科书上的标准答案说“它是前人总结的、针对特定问题的可复用解决方案”。这话没错但太抽象了背下来也没用。我的理解更朴素设计模式的本质是“封装变化”。哪个地方容易变就把它隔离出来用接口或抽象类约定好然后让具体实现各自飞。你抓住“变化”这两个字23个模式瞬间就有了归属感。比如创建型模式变化的是什么是“对象怎么创建、由谁创建”。你直接new一个具体类一旦需求变了要换一个实现类你得满世界找那个new语句。简单工厂就是把“创建哪个类”这个变化点收拢到一个工厂类里。结构型模式呢变化的是“对象之间的关系怎么组织”。适配器要解决的是“接口对不上”的变化代理解决的是“要不要在访问前后加点东西”的变化。行为型模式更直接变化的是“算法、职责、状态怎么交互”策略模式就是把“算法族”整个拎出来互相替换。打个比方。你把设计模式想象成装修房子创建型模式管的是“建材从哪来、怎么进场”——工厂是统一采购单例是家里只有一个总电闸。结构型模式管的是“房间怎么隔、家具怎么摆”——适配器是转换插头代理是物业门禁。行为型模式管的是“住在里面的人怎么协作”——策略是换个厨具做法不变观察者是门铃一响所有住户都知道了。这样一归类再往具体模式里钻你会发现每个模式解决的“变化点”都是唯一的。理解了“模式封装一个变化点”这个底层逻辑你记的就不是23个孤立的条目而是一棵有主干、有分支的树。主干上写着“封装变化”三个大枝杈分别是“创建、结构、行为”每个枝杈上挂着一堆叶子每片叶子对应一个具体变化场景。2. 三大工厂模式的“套娃”关系记不住的根本原因是不知道它们怎么来的热词榜上“简单工厂模式”排第一搜索量最大“工厂模式”排在C相关的第二。这三兄弟简单工厂、工厂方法、抽象工厂是初学者最容易懵的因为它们的代码长得太像了。我直接说结论简单工厂是“入门版”工厂方法是“升级版”抽象工厂是“终极版”。它们不是在讲三个完全不同的东西而是在讲“对象的创建这件事怎么一步步解耦”。2.1 简单工厂一个if-else走天下但别指望它扛大梁简单工厂为什么叫“简单”因为它真的简单。你有一个工厂类里面放一个静态方法根据传入的参数用if-else或者switch去new不同的产品子类。调用方不用自己new了只需要传一个字符串或枚举进去工厂替你做决定。// Java版简单工厂 public class OperationFactory { public static Operation createOperation(String operate) { Operation op null; switch (operate) { case : op new OperationAdd(); break; case -: op new OperationSub(); break; case *: op new OperationMul(); break; case /: op new OperationDiv(); break; } return op; } }这是《大话设计模式》里计算器的经典案例也是我见过的大作业最常见的开头。但注意简单工厂有个硬伤每加一个新运算你都得打开工厂类改switch。它把“创建”从客户端挪到了工厂算是解耦了一半但工厂类和具体产品还是耦合的。对学习来说它是完美的入门教材对工程来说它扛不住频繁扩展。期末笔试如果问“简单工厂的缺点是什么”标准答案就是“违背开闭原则扩展需要修改工厂类”。C版本原理完全一样区别只在语法。C的工厂函数一般返回unique_ptr或shared_ptr避免裸指针泄漏Java那边返回对象引用就行垃圾回收替你兜底。有的教科书会把简单工厂叫“静态工厂方法”因为它通常用static修饰这也是笔试爱挖的坑——简单工厂不是GoF的23种模式之一它是大家为了方便起的俗称。考判断题的时候留个心眼。2.2 工厂方法把“创建”的权力下放给子类既然简单工厂的switch会越改越长那干脆把“创建”这个动作延迟到子类去做。工厂方法模式的经典结构是一个抽象工厂类或接口定义了一个抽象的createProduct()方法每个具体工厂子类自己实现“我到底要new哪个产品”。客户端面对的是抽象工厂实际调用时拿到的是具体工厂由它生产对应的具体产品。// Java版工厂方法 public interface IFactory { Operation createOperation(); } public class AddFactory implements IFactory { public Operation createOperation() { return new OperationAdd(); } } public class SubFactory implements IFactory { public Operation createOperation() { return new OperationSub(); } } // 客户端 IFactory factory new AddFactory(); Operation op factory.createOperation();口诀就四个字“工厂也抽象”。以后想扩展减法不用改旧代码加一个SubFactory类就行。从“简单工厂的修改”变成“工厂方法的扩展”这就是开闭原则的体现——对扩展开放、对修改关闭。C实现工厂方法时抽象工厂通常长这样// C版工厂方法 class IFactory { public: virtual std::unique_ptrOperation createOperation() 0; virtual ~IFactory() default; }; class AddFactory : public IFactory { public: std::unique_ptrOperation createOperation() override { return std::make_uniqueOperationAdd(); } };注意C里必须给抽象工厂一个virtual析构函数不然delete基类指针时子类析构函数不会被调用内存泄漏警告。这个考点几乎每次C设计模式相关的大作业评审都会提到。2.3 抽象工厂当产品不再是“单个”而是一个“家族”到了抽象工厂问题升级了。前面工厂方法只管“生产一种产品”但现实里经常要生产“一族产品”。比如做数据库访问你有User表、Department表同时你有SQL Server、MySQL两种数据库。如果你只关心“创建User的操作对象”一个工厂方法就够但如果你希望“MySQL版创建User和Department的对象、SQL Server版创建User和Department的对象”那就得用抽象工厂——它定义的是一个“产品族”的创建接口。// Java版抽象工厂 public interface IDatabaseFactory { IUser createUser(); // 创建操作User表的对象 IDepartment createDepartment(); // 创建操作Department表的对象 } public class MySqlFactory implements IDatabaseFactory { public IUser createUser() { return new MySqlUser(); } public IDepartment createDepartment() { return new MySqlDepartment(); } } public class SqlServerFactory implements IDatabaseFactory { public IUser createUser() { return new SqlServerUser(); } public IDepartment createDepartment() { return new SqlServerDepartment(); } }看明白了吗工厂方法管的是“同类产品里的不同实现”抽象工厂管的是“多个产品线的配套实现”。笔试基本必考一道“工厂方法vs抽象工厂”对比题最高频的答法就是工厂方法针对产品等级结构抽象工厂针对产品族。什么叫产品等级结构就是“键盘”这个抽象下分“机械键盘、薄膜键盘”。什么叫产品族就是“机械键盘游戏鼠标电竞耳机”这一整套电竞外设。抽象工厂保证你从MySqlFactory拿到的所有东西都是MySQL家的不会出现“SQL Server的User对象搭配MySQL的Department对象”这种驴唇不对马嘴的组装错误。三个工厂放一起记用一张表就清清楚楚模式封装的变化点一句话记忆核心缺点简单工厂具体产品类的选择一个类用switch决定new谁扩展要改工厂违背开闭原则工厂方法创建对象的具体类工厂也抽象子类决定new谁每加一种产品就要加一个工厂类类数量膨胀抽象工厂产品族的整体风格一组配套产品统一生产加一个新产品线要动抽象工厂接口牵连所有实现最后一列那个“缺点”也很重要。超级工厂模式看着高大上但面试官最爱追问“抽象工厂的缺点”你如果答“很完美”印象分直接打对折。正确答案是抽象工厂在“横向加产品族”时很爽但“纵向加单品”时很痛苦——每加一种新表对应的类你要改接口、改所有实现类。所以抽象工厂适合产品族相对稳定的场景不适合产品类型频繁扩张的场景。3. 策略模式把“算法怎么变”单独抽出来比switch优雅一个量级热词里“设计模式策略模式”也上了榜。策略模式的理解门槛不高但它在面试里被问到的频率极高因为太贴近真实业务了。它的核心定义是定义一族算法分别封装起来让它们之间可以互相替换。算法的变化不影响使用算法的客户端。最常见的例子是商场收银。平时不打折节假日满300减100店庆打八折清仓打五折。你当然可以写一个switch (type)然后case里套不同的打折逻辑。但问题跟简单工厂一样——每次促销一变你就要改收银类还可能改出bug来。用策略模式就是把“打八折”“满减”“五折”各写一个策略类实现同一个接口然后让收银上下文持有一个策略对象运行时替换。// Java版策略模式 public interface ISale { double acceptCash(double price, int count); } public class CashNormal implements ISale { public double acceptCash(double price, int count) { return price * count; } } public class CashRebate implements ISale { private double rebate; public CashRebate(double rebate) { this.rebate rebate; } public double acceptCash(double price, int count) { return price * count * rebate; } } public class CashReturn implements ISale { private double condition, ret; public CashReturn(double condition, double ret) { this.condition condition; this.ret ret; } public double acceptCash(double price, int count) { double total price * count; return total condition ? total - Math.floor(total / condition) * ret : total; } }这个例子的精髓在于算法被封装成了独立对象上下文的代码完全不变。想加新促销新写一个类实现ISale塞进去就行。用策略模式改写掉大型if-else链是代码重构里最有成就感的一件事。但这里我要提醒一句策略模式有个容易忽视的坑策略类的数量会膨胀。每多一种算法就多一个类如果算法本身就几个收益明显如果算法有几十个用策略模式反而让类爆炸。这时候就要考虑“策略简单工厂”合体——让工厂负责根据条件创建策略对象客户端只管传入类型这个组合也是“设计模式大作业”里最受欢迎的套路之一。C版策略模式习惯上会用std::function配合lambda简化少写几个类// C11之后的策略模式简化版 #include functional using SaleStrategy std::functiondouble(double, int); SaleStrategy normal [](double price, int count) { return price * count; }; SaleStrategy rebate [rebate 0.8](double price, int count) { return price * count * rebate; }; // 上下文 class CashContext { SaleStrategy strategy; public: void setStrategy(SaleStrategy s) { strategy std::move(s); } double getResult(double price, int count) { return strategy(price, count); } };看到区别了吗Java的策略模式必须严格定义接口加多个实现类这是它的语法特性决定的C有了lambda和std::function直接把“算法族”当函数对象传来传去代码量少一半但模式思想完全一样。所以无论是考试写伪代码还是做项目抓住“算法该独立于场景变化”策略模式就算学会了至于用接口还是lambda那是实现细节。4. 组合模式树形结构的一把钥匙大作业里的大热门“大话设计模式 组合模式”上了热词搜索说明很多人正在被这玩意儿卡住。组合模式的适用场景非常清晰当你的数据结构是“部分-整体”的树形层次时比如公司组织架构总公司—分公司—部门—员工、菜单系统菜单—子菜单—菜单项、文件系统文件夹—子文件夹—文件。组合模式的核心思想是让叶子节点和容器节点实现同一个接口客户端不用区分“我调的是单个文件还是整个文件夹”统一调用一个方法就行。如果用Java写一个菜单示例// Java版组合模式 public abstract class MenuComponent { protected String name; public abstract void add(MenuComponent component); public abstract void remove(MenuComponent component); public abstract void print(); } public class MenuItem extends MenuComponent { // 叶子 public MenuItem(String name) { this.name name; } public void add(MenuComponent component) { throw new UnsupportedOperationException(); } public void remove(MenuComponent component) { throw new UnsupportedOperationException(); } public void print() { System.out.println( - name); } } public class Menu extends MenuComponent { // 容器 private ListMenuComponent children new ArrayList(); public Menu(String name) { this.name name; } public void add(MenuComponent component) { children.add(component); } public void remove(MenuComponent component) { children.remove(component); } public void print() { System.out.println( name); for (MenuComponent c : children) c.print(); } } // 客户端 MenuComponent fileMenu new Menu(文件); fileMenu.add(new MenuItem(新建)); fileMenu.add(new MenuItem(打开)); fileMenu.add(new MenuItem(保存)); fileMenu.print();组合模式有两个容易被问到的点。一个是透明式和安全式的区别。上面这个例子是“透明式”——叶子节点也有add/remove方法只不过抛异常因为抽象类里定义了这些方法。这么做的好处是客户端把叶子当容器用完全统一坏处是叶子节点多出了几个没用还得抛异常的方法。另一种“安全式”是把add/remove定义在Menu里MenuItem里干脆没有客户端如果想统一调用add得自己先判断类型失去了透明性。真实项目里安全式更常用因为“不提供做不到的方法”总比“提供了再抛异常”更符合直觉但笔试爱考透明式因为它更标准。第二个坑是递归遍历别写成死循环。容器里套容器一不小心children里把自己加进去一打印就StackOverflow。还有一个常见失误是用组合模式做文件系统时把“删除文件夹”做成了只删容器不删叶子“递归删除”这种细节大作业验收时必被追问。5. 期末考、大作业、面试三个场景的“应试策略”热词搜到“设计模式期末”“设计模式大作业”“设计模式java实现”“java设计模式电子书刘伟著”明显能看出搜索设计模式的人里学生占了相当高比例。所以实用经验这块我分开三个场景说。5.1 期末笔试怎么拿分期末笔试考设计模式无非三类题第一类是概念辨析题。比如“简单工厂和工厂方法的区别”“策略模式和状态模式的区别”“装饰模式和代理模式的区别”。碰到这种题不要只背定义要画出类图。笔试卷子上没有类图你自己在草稿纸上画一遍思路立刻清晰。策略模式和状态模式的区别其实就在“谁来触发变化”策略是客户端主动换算法状态是状态对象内部自己切换下一状态。这个差别用一句话讲“策略是被动换状态是自动串”就记住了。第二类是读代码改代码题。给你一段用if-else写死的计算器代码让你用工厂方法重构。这种题考的就是类图的基本功你只要记得“抽象产品、具体产品、抽象工厂、具体工厂”四件套照着套就没问题。注意一个细节题目说“用工厂方法重构”你千万别写成简单工厂——很多同学区分不了这两个概念一紧张就写了个静态方法加switch挡在那里白白丢分。第三类是找出代码的坏味道并给出改进方案。高频坏味道就是长方法、重复代码、switch/if-else过多、类过大。看到“switch太多”优先想到策略模式或工厂看到“new过多”优先想到工厂方法看到“功能太多的大类”优先想到单一职责组合模式往往配合着凑上来。5.2 大作业怎么设计才能拿高分设计模式大作业普遍是“计算器”“购物车”“停车场”这类选题因为好建模、模式用得上。但绝大多数人都是“用工厂模式创建了所有对象”就完了属于把模式硬贴上去老师一眼就能看出来。拿“购物车”举例我的建议是这样分配模式工厂方法负责创建不同类型的商品图书、电子产品、生鲜策略模式处理计价规则——普通会员、黄金会员、铂金会员的折扣逻辑各不相同观察者模式做库存更新和通知商品售罄时自动通知相关模块单例模式管购物车本身或数据库连接保证全局唯一组合模式做商品分类树——首页的“电子”分类下面是“手机”“电脑”“电脑”下面还能再分“笔记本”“台式机”。你看这样一设计整个项目就有了层次不是“用模式秀肌肉”而是“每个模式都在解决一个真实变化点”。大作业答辩时老师最常问“你这个模式是不是硬套的”——你要是能说清楚“这个变化点在哪”“为什么选这个模式不用另一个”基本就稳了。如果不知道怎么开头可以去搜“刘伟 设计模式 java”那本《Java设计模式》虽然厚但类图非常多照着它的课后题做练习效率很高。5.3 面试怎么答才显深度面试和期末考的差别在于面试官不只想知道“你会用”还要听你说出“为什么这么用”“还有没有更好的方案”。比如他问“了解策略模式吗”你正常答完定义如果能追加一句“这个模式跟if-else的本质区别在于把算法从上下文中剥离让上下文只依赖策略接口从而可以在运行时替换”面试官就会觉得你是真懂不是背的。还有几个高频追问要提前预备好“单例模式一定有线程安全问题吗你平时怎么写线程安全的单例”——直接答“双重检查锁DCL volatile”或者“静态内部类方式”Java、“Meyers Singleton”C11之后的局部静态变量。“让你设计一个登录系统你会用哪些模式”——这个开放题没有标准答案我常用的切法是单例管用户会话、策略管第三方登录方式微信/QQ/手机号、观察者管登录后的通知下发再加一个门面模式统一对外接口。能抛出三四个模式并解释清交互关系基本就能过关。还有一个很现实的经验面试手写代码千万别炫技用最朴素的写法把模式的核心结构搭出来。我看到过太多人非要写一个花式工厂结果语法错误一堆。设计模式考的是思想和结构不是语法花活这点哪怕进大厂也一样适用。6. 一套能记住所有模式的“自检口诀”和速记卡片最后分享一个我自己总结的速记思路不是让你背而是把它当“记忆锚点”。每个模式我都用“一句话场景一句话方案一句口诀”来记模式一句场景核心方案记忆口诀简单工厂用参数决定new谁一个工厂类集中创建工厂switch简单但改类工厂方法每个产品一个创建者工厂抽象化子类决定工厂也抽象多态来创建抽象工厂一组配套产品必须一起换一个工厂管整个产品族产品族统一扩展累死你策略算法要能随时换算法独立成类上下文注入把算法拎出来随便换组合树形结构统一处理叶子容器共用接口叶子当容器递归打印去单例全局只有一份私有构造静态入口构造私有化实例只一份观察者状态变了要通知别人发布-订阅解耦主题广播观察者响应装饰器给对象动态加功能一层套一层包套娃扩展不改原类适配器接口对不上中间层转接口加个插头接上就能用代理访问目标前后要加东西替身对象控制访问找人代办控制入口模板方法步骤固定但细节可变基类定骨架子类实现步骤骨架定好细节自己填状态状态变了行为跟着变状态封装成对象状态一走行为自动换怎么利用这张表我的做法是每次学一个新模式先看“一句场景”问自己“如果是我遇到这个问题会怎么写代码”想完再看“核心方案”。自己踩过一遍坑之后再看口诀记忆会特别牢。光盯着“定义”“结构图”是记不住的必须让大脑经历“问题→方案”的对照过程。另外给你一个查漏补缺的刷题路径找网上经典的“8种行为型模式代码剖析”或者“最常用的10个设计模式”这类资源逐个对着自己的项目场景过一遍。相比把23个模式从头到尾背一遍“高频高频”的反复打磨会让你在真正需要用的时候反应更快。我在应对面试时反而只精讲五六个模式单例、工厂、策略、观察者、装饰器、组合但每一个都能聊到优缺点和适用边界这就比把23个都背得半生不熟要实用得多。设计模式这东西短期速记靠的是分类和方法论长期掌握靠的是写代码时下意识地想到“哎这里的变化点好像可以用XX模式”。你现在背下来应付期末考出去工作后会发现它已经变成肌肉记忆了。把前面那六个核心模式吃透再回头看书其他所谓“冷门模式”其实也就是几个同样道理换个姿势而已。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。