拓冰建站拓冰建站
首页 / 资讯中心 / 正文

【设计模式精讲】9.创建型模式总结与对比

【设计模式精讲】9.创建型模式总结与对比【摘要】五种创建型模式学完真正的问题才开始面对一个具体需求五个都能「造对象」该派谁上场本文先回到 GoF 的统一视角——创建型的共同命题是把「对象怎么造」从「对象怎么用」中解耦参数化系统的两种途径继承与组合决定了五个模式的分野随后给出一张横向对比总表与逐项辨析重点展开 GoF 的经典案例同一个「绘图工具造图形」需求分别用工厂方法、抽象工厂、原型实现并评估得失最后给出选择决策树与速记口诀并归纳「先简单后复杂」的演化路径与模式间的组合用法为进入结构型篇章收口。【关键词】创建型模式、横向对比、决策树、参数化、模式协作1. 五个模式一个命题回顾第 4 至 8 篇单例管「唯一」工厂方法管「谁决定类型」抽象工厂管「一族配套」建造者管「分步装配」原型管「复制现成」。表面五花八门GoF 在「创建型模式讨论」一节点破了它们的统一命题把系统「创建哪些类的对象」这件事参数化让客户代码只面对抽象。参数化有两条路这正是五个模式的分水岭。其一是继承把「造什么」写成可重写的操作子类替换之——这是工厂方法的路子GoF 指出它的代价是「仅仅为了换一个产品类就得新建一个子类」且改动可能级联创建者自己也是被工厂方法造出来的就要一路重写上去。其二是组合定义一个专职的「工厂对象」让它负责知道产品类再把这个对象作为参数传给系统——抽象工厂、建造者、原型都走这条路抽象工厂的工厂对象一次造多种产品建造者的工厂对象按一套复杂协议逐步攒一个复杂产品原型的工厂对象靠复制自己造产品——此时工厂对象与原型是同一个对象。单例是个特例它参数化的不是「造哪个类」而是「造几次、谁能拿到」。理解了这个坐标系对比表里的每一行就不再是孤立的知识点而是两条路线上的不同站点。2. 横向对比总表模式一句话意图关键问题造的对象核心手段典型场景单例第 4 篇唯一实例 全局访问点造几个一个永远同一个私有构造 静态instance()日志器、配置中心工厂方法第 5 篇子类决定实例化哪个类谁决定类型一个继承虚函数重写框架挂钩、类型渐增抽象工厂第 6 篇造一族相关对象配不配套一族组合工厂对象一次多造跨平台 UI、多后端建造者第 7 篇分步构造复杂对象几步装一个复杂的组合工厂对象按协议分步HTTP 请求、SQL、配置原型第 8 篇复制已有对象从零还是从有一个现成的副本组合对象自克隆clone()工具箱模板、撤销快照三个纵列最值得横着读。「关键问题」列是选型的第一过滤器先问自己最头疼的是数量、类型决定权、配套、步骤还是复制答案直接锁定模式。「核心手段」列呼应第 1 节的继承/组合分野——这也解释了 RG 的对比结论工厂方法基于继承但无需初始化步骤原型不基于继承没有继承的缺点却要对被复制对象做复杂初始化。「典型场景」列提醒边界表中任何一格挪到别的格都别扭——比如给「造一个复杂对象」硬上抽象工厂收获的只是一堆单方法接口。各自的常见误用也顺带清点单例被当「懒得接线」的全局变量工厂方法被用在类型从不变化的场合GoF 明说此时没必要抽象工厂被只有单一变体的项目提前引入建造者被三五个稳定参数的小对象拖出来凑数原型被误当成「少写构造函数」的捷径忘了它只服务于多态复制。3. 同一需求的三种解法GoF 的绘图编辑器抽象的对比不如同题竞争。GoF 用绘图编辑器框架做了经典实验工具箱里每个工具GraphicTool要能造出对应图形Circle、Line……同一个需求三种模式分别怎么出手工厂方法方案每个图形子类配一个GraphicTool子类重写NewGraphic()。优点是起步最容易——定义子类即可工具实例只在定义调色板时创建缺点是GraphicTool子类泛滥而每个子类都没干什么实事。抽象工厂方案建一族GraphicFactory每个图形一个CircleFactory造Circle……工具由参数注入对应工厂。GoF 的判词很直接没有带来实质改进——工厂类层次与工具子类层次一样庞大只有当系统中本来就有这族工厂类或其他部分需要它时抽象工厂才优于工厂方法。这条判据比「产品是不是一族」更严格还要问这一族是否已被系统需要。原型方案每个图形类实现Clone()工具持有一个原型实例要新图形就克隆。GoF 的结论是它对该框架可能是最优的只需在每个图形类上实现一次克隆类数量最少而且Clone还能顺手复用于「复制选中对象」的菜单功能——一鱼两吃。这个案例的教学价值在于模式选型不是对错题是权衡题。三个方案都能工作差异体现在类数量、扩展成本与功能复用上GoF 还补了两个通用结论——工厂方法「只要求新操作、不要求新类」常被当作标准创建手段但被实例化的类从不变化时就没必要而抽象工厂、原型、建造者比工厂方法更灵活也更复杂所以设计常常从工厂方法起步随灵活性需求显现再演进——这与 RG 的观察一致。4. 选择决策树把以上判据收进一棵决策树按提问顺序自上而下依次过滤多数需求走不到第三层就能定案是否是否是否是是否否是否要造对象实例必须唯一且全局访问?单例对象复杂、参数多步骤多?建造者只持有接口、想复制现成对象?原型多种产品必须成族配套?该族工厂体系系统本就需要?抽象工厂抽象工厂或逐个工厂方法类型会增长、创建点在框架里?工厂方法或注册表直接构造make_unique 即可树上有两处特别标注的「灵魂拷问」值得强调。另外注意这棵树回答的是「第一次选型」已有系统重构时先用树找到目标形态再对照第 3 节的演化路径规划中间台阶一步到位的豪赌不如两步走的稳妥。问 H 之后追问「工厂体系是否本就需要」来自第 3 节 GoF 的判例不要为了成族而造成族。走到 N 分支同样重要——「不用模式」是合法且常是最优的选项类型不变、构造简单时make_uniqueT加一个自由函数就够注册表那套全局状态与初始化时序的心智负担只有类型确实持续增长才值得背负。5. 速记口诀一张表一棵树之外再给一段便于回忆的口诀每句对应一篇唯一记单例选型问子类成族配套厂中厂分步攒件用建造已有现成抄原型不增类型直接造。拆开讲实例天然唯一找单例第 4 篇「谁决定类型」交给子类重写就是工厂方法第 5 篇「厂中厂」即工厂的工厂——抽象工厂一族一个厂第 6 篇构造过程漫长多步找建造者第 7 篇能复制现成对象就克隆第 8 篇最后一句是反向提醒——什么都不变时别造任何工厂。6. 模式间的协作与演化五种模式并非互斥选项真实工程里它们常常搭伙。GoF 与 RG 都给过明确说法归并成四条抽象工厂通常由一组工厂方法实现第 6 篇已见但也可以用原型来实现——工厂不再new各产品而是持有一组原型克隆交货抽象工厂、建造者、原型都可以用单例实现——那「一个」工厂/建造者/原型表本身往往全局唯一第 8 篇的注册表就是「原型 单例」的合体建造者常与组合第 14 篇配合递归构造组合树时建造步骤天然递归演化路径项目初期用工厂方法简单、子类可定制随后按痛点演进——配套需求出现升抽象工厂复制需求出现升原型步骤复杂化升建造者。反过来则罕见一开始就铺满五个模式的「全家桶」设计几乎注定过度设计——每多一层抽象团队就要多付一份理解与维护的税而这份税只有在变化真的到来时才物有所值。本专栏后续还会反复回访这套演化观创建型解决「对象从哪来」结构型解决「对象怎么组装」——下一篇适配器开场我们由此进入专栏第二部分。本篇小结创建型五模式的统一命题是「创建与使用解耦」分野在参数化的两条路工厂方法走继承抽象工厂、建造者、原型走组合单例独守「唯一」。选型时先过「关键问题」过滤器再用决策树追问两层灵魂拷问工厂体系是否本就需要类型是否真的会增长拿不准时记住 GoF 的实验结论同题三解皆可行差异是权衡而非对错从工厂方法起步、按需求演进。口诀收口唯一记单例选型问子类成族配套厂中厂分步攒件用建造已有现成抄原型不增类型直接造。本文的两种参数化途径与绘图编辑器对比案例参考了 GoF《Design Patterns》第 3 章「Discussion of Creational Patterns」一节模式间关系与演化路径参考了 Refactoring Guru《设计模式》中文版各篇「与其他模式的关系」小节。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门