设计模式(开卷考速查背诵单)
提示:本资料重点整理了题目要求的模式类图结构、核心代码实现逻辑,适合打印后直接带入考场作为参考。
第一部分:面向对象设计与重构(作业01)
1. 游戏角色与装备系统
- 涉及原则:
- 单一职责(SRP):Character管角色属性/攻击,Shop管交易,不混在一起。
- 开闭原则(OCP):新增项链装备,只需派生并实现接口,无需改原有逻辑。
- 依赖倒置(DIP):角色依赖于
IEquipable接口或Item抽象类,而不是具体武器类。
- UML与关系:
- 泛化(继承):
Weapon,Armor,Ring——▷Item(抽象类)。 - 实现:装备类 ···▷
IEquipable接口。 - 组合/关联:
Character包含 1个Backpack(生命周期一致,用组合),Backpack聚合多个Item(物品可脱离背包独立存在,用聚合)。
- 泛化(继承):
- 核心逻辑:
攻击方法
attack(Character target)内部计算:max(this.totalAtk() - target.totalDef(), 1)。
2. 订单系统重构
- 原代码问题:
Order类包含了数据存储、总价计算、数据库保存、发送邮件4个功能。严重违反单一职责原则。内部系统强耦合。 - 重构结构:
- 数据层:
Order仅保留items列表及增删查方法。 - 计算层:
OrderCalculator提供calculate(Order order)。 - 持久化层:定义
OrderRepository接口,实现类DatabaseOrderRepository->save(Order order)。体现依赖倒置。 - 服务层:定义
EmailService接口,实现类SmtpEmailService->sendEmail(Order order)。
- 数据层:
第二部分:生成型与部分行为型(作业02)
| 题号 | 业务场景 | 所选模式 | UML结构与核心代码精要 |
|---|---|---|---|
| 1 | 计算器重构 | 策略 (Strategy) | 结构:Context持有一个运算接口 ICalculator代码: class Add : public ICalculator { double calc(a,b){return a+b;} }。客户端根据操作符实例化不同的策略给Context。 |
| 2 | 校服生产 | 抽象工厂 (Abstract Factory) | 结构:IUniformFactory 定义 createSummer() 和 createAutumn()代码:一中工厂 School1Factory 实现上述方法返回特定的夏/秋校服。保证同学校产品族配套。 |
| 3 | 数据导出 | 模板方法 (Template Method) | 结构:抽象类定义 export() 模板,和抽象步骤代码: export(){ buildHeader(); buildBody(); buildFooter(); }。具体如XmlExport重写具体步骤。 |
| 4 | 序列号生成 | 单例 (Singleton) | 核心:private 构造函数;private static instance;public static getInstance()。只有通过getInstance获取,保证全局唯一。 |
| 5 | 数据库连接 | 多例 (Multiton) | 核心:private static vector<DBConnections> pool。可通过单例演化,上限为3。当请求超过数量时,可轮询返回或抛出异常。 |
| 6 | 日志系统 | 工厂方法 (Factory Method) | 结构:LogFactory 接口有 createLog()。客户端面向接口编程。代码: FileLogFactory 专造 FileLog,增加新日志时只需增加新工厂类。 |
| 7 | 角色皮肤搭配 | 桥接 (Bridge) | 结构:角色 Role 持有 皮肤接口 Skin。将两个维度的变化分离。代码: class Warrior : public Role { void display(){ skin->show(); } }。组合优于继承。 |
| 8 | 试卷生成 | 原型 (Prototype) | 代码:实现 clone() 方法。由于有可变的考生信息,clone 时必须进行深拷贝(Deep Copy),重新分配内存保存个人信息。 |
| 9 | 配置管理器 | 单例 + 工厂 | 核心:配置管理器本身是单例,但它内部处理多种XML/Properties解析策略时,使用简单工厂来生成对应格式的 Parser。 |
| 10 | 文档模板 | 原型 + 工厂 | 核心:工厂类内部维护一个 Map<string, DocumentPrototype>。当客户端请求某种模板时,工厂 return map[type]->clone() 返回克隆对象。 |
第三部分:结构型与行为型(作业03)
| 题号 | 业务场景 | 所选模式 | UML结构与核心代码精要 |
|---|---|---|---|
| 1 | 跨播放器支持 | 适配器 (Adapter) | 结构:MediaPlayerAdapter 实现标准目标接口,内部持有一个 WindowsPlayer 或 RealPlayer 实例(对象适配器)并调用其专属API。 |
| 2 | 调度器跨平台 | 桥接 (Bridge) | 结构:调度器 Scheduler(如时间片/抢占)包含 操作系统 OS(如Win/Linux)。运行时动态将某调度器绑定到某平台上。 |
| 3 | 时价饮品配料 | 装饰器 (Decorator) | 结构:Beverage 接口。CondimentDecorator 继承Beverage并持有一个Beverage。代码: return beverage.price() + this.price; 动态叠加价格。 |
| 4 | 菜单与菜式 | 组合 (Composite) | 结构:MenuComponent 基类。叶子: MenuItem。树枝: Menu(含vector<MenuComponent*>)。一致对待单个对象和组合对象。 |
| 5 | 复杂奖金计算 | 组合 + 策略 | 结构:各种发钱名目作为Strategy(单项奖、团队奖)。部门经理的奖金计算策略可能是由多个单项策略组合(Composite)而成,逐项累加。 |
| 6 | 相册树+特效 | 组合 + 装饰 | 结构:将照片和按年月日的文件夹变成组合关系。对底层的单一照片对象包一层装饰器(加花边/音效),不改变其原节点接口。 |
| 7 | 编译流程极简化 | 外观 (Facade) | 结构:客户端 -> CompilerFacade -> {词法,语法,优化等}。代码: Facade.compile() 内部按顺序依次调用各复杂子系统的API。 |
| 8 | 多渠道支付接入 | 适配器 (Adapter) | 类似题1,微信和支付宝 SDK 各异。WechatAdapter 继承 UnifiedPay,在 pay(amount) 中转换参数去调用微信的特有请求函数。 |
| 9 | 长文档内存优化 | 享元 (Flyweight) | 结构:字符对象只存内在状态(字体/大小)。 代码:使用 FlyweightFactory 共享字符实例。渲染时 draw(int x, int y) 传入外部位置状态。 |
| 10 | 大报表懒加载+边框 | 代理 + 装饰器 | 结构:ReportProxy 延迟加载真实报表(虚拟代理)。在代理返回前,外层可以再套 HeaderDecorator, WatermarkDecorator 动态加修饰。 |
第四部分:行为型进阶与机制(作业04)
| 题号 | 业务场景 | 所选模式 | UML结构与核心代码精要 |
|---|---|---|---|
| 1 | 报销层级审批 | 责任链 (CoR) | 代码:每个处理器持有 nextApprover。if (amount < threshold) { handle(); } else { nextApprover->handle(); }。 |
| 2 | 点餐排队后厨做 | 命令 (Command) | 核心:点餐请求封装为 OrderCommand。服务员(Invoker) takeOrder(cmd)。厨师为(Receiver)。解耦请求的发送者与执行者。 |
| 3 | 病房呼叫广播 | 观察者 (Observer) | 核心:病房呼叫机为 Subject,大厅广播、护士站屏幕为 Observers。状态改变时调用 notify() 通知所有监听者动作。 |
| 4 | 新物业注册通知 | 工厂 + 观察者 | 核心:每次使用 工厂方法 创建一套公寓/商铺后,在出厂前触发事件,通知主管(观察者)进行记录和审查。 |
| 5 | 火灾探头联动 | 观察者 (Observer) | 同题3。FireDetector (Subject)。警报器、防火门等均实现 FireObserver 接口,注册在探测器上。着火统一调用 update()。 |
| 6 | 昼夜金库安防 | 状态 (State) | 代码:金库由 VaultContext 代理,其状态指针动态指向 DayState 或 NightState。打电话方法在两状态类中的实现截然不同。 |
| 7 | 恒温器开关 | 状态 (State) | 核心:温控器在系统开启/关闭下能响应的指令不同,指令行为直接委派给内部的 OnState 或者 OffState 处理类。 |
| 8 | 影票分类折扣 | 策略 (Strategy) | 代码:定义 DiscountStrategy 接口。打折时 context.calculate(originalPrice) 内部执行 strategy.apply(price)。随时扩展VIP打折卡。 |
| 9 | 算法步骤局部分歧 | 策略 + 模板方法 | 合并:在策略的父类中提供 templateMethod() 作为骨架,抽取出公共步骤,将个别特异步骤抽象,留给子类(也是具体策略)重写。 |
| 10 | 事件循环/回调 | 观察者(变体) | 核心:Trigger 类内部有 map<string, vector<function>> events。on 方法注函数入map,raiseEvent 按key遍历执行所有函数。 |
第五部分:考场实战(如何根据题干字眼一秒锁定设计模式)
在考场上,当你看到题目描述中的某些高频关键词或特定业务场景时,可以迅速对应该用什么模式:
1. 创建型(管怎么“生”对象)
| 题干关键字 / 业务场景 | 应选模式 | 核心思路 |
|---|---|---|
| “全局唯一”、“只能有一个实例” | 单例模式 (Singleton) | 构造私有化,内部保留静态实例。 |
| “最多只能存在N个对象” | 多例模式 (Multiton) | 单例的变种,内部用 vector 或 List 存N个实例。 |
| “克隆”、“生成大量相似对象”、“重新初始化太耗时” | 原型模式 (Prototype) | 提供 clone() 方法,注意内存深拷贝问题。 |
| “不修改现有代码的前提下增加新对象”、“不知道具体类名” | 工厂方法 (Factory Method) | 把 new Obj() 的逻辑推迟到具体子类工厂去做。 |
| “生产一套配套的产品”、“系列(如春夏校服)” | 抽象工厂 (Abstract Factory) | 一个大工厂接口定义生产全套(多个)部件的方法。 |
2. 结构型(管怎么“拼”对象)
| 题干关键字 / 业务场景 | 应选模式 | 核心思路 |
|---|---|---|
| “兼容旧接口”、“第三方API接入”、“接口格式不一致” | 适配器模式 (Adapter) | 包一层!把不兼容的接口转成系统期待的接口。 |
| “多维度独立扩展”、“避免类爆炸(多重继承)” | 桥接模式 (Bridge) | 组合优于继承!如把“角色”和“皮肤”分开,在角色里 组合 一个皮肤接口。 |
| “树形结构”、“整体与部分处理方式一致(如菜单/目录)” | 组合模式 (Composite) | 节点和叶子继承同一个基类,树枝内部有一组基类指针。 |
| “动态增加功能/特效”、“层层叠加(如相框、饮料加料)” | 装饰器设计 (Decorator) | 继承并包含!自己是某接口子类,内部又持有一个该接口的对象。 |
| “提供统一入口”、“隐藏内部子系统复杂性” | 外观模式 (Facade) | 搞个高级接待员(统一门面类),客户端只跟接待员打交道。 |
| “懒加载”、“不真正使用就不加载”、“加控制/权限” | 代理模式 (Proxy) | 假李鬼代理真李逵,请求过来先判断,必要时再实例化真身。 |
| “大量颗粒度小的对象”、“内存溢出”、“共享同一属性” | 享元模式 (Flyweight) | 分离内在/外在状态。内部对象存池子里复用,外部坐标等参数在渲染时传。 |
3. 行为型(管怎么“跑”业务)
| 题干关键字 / 业务场景 | 应选模式 | 核心思路 |
|---|---|---|
| “多种算法自由切换”、“打折规则多变”、“消除大量 if-else” | 策略模式 (Strategy) | 把具体的计算规则封装成类,主类里留一个规则的接口指针。 |
| “按金额层级审批”、“不知道谁能处理,依次向后推” | 责任链 (CoR) | 每个处理者只判断“我能不能管”,不能管就 next->handle()。 |
| “排队处理”、“记录请求日志”、“发送与执行解耦” | 命令模式 (Command) | 把“动作(点菜)”本身变成一个个对象,扔进队列让别人慢慢执行。 |
| “联动”、“A发生变化,通知B/C/D动作”、“广播”、“事件处理” | 观察者模式 (Observer) | A维护一个订阅者列表,出事了循环调里面每个订阅者的 update()。 |
| “不同状态(昼夜/开关)行为完全不同”、“避免状态枚举的臃肿判断” | 状态模式 (State) | 把具体的行为委托给具体的状态类(每个状态是一个类)。 |
| “大体流程一致,只有局部个别步骤不同” | 模板方法 (Template) | 父类定好 step1(); step2(); step3(); 骨架,子类只重写特异的 step2()。 |
评论区 - 设计模式_开卷考速查表