设计模式入门:创建型、结构型、行为型

反复出现的「怎么造对象、怎么拼结构、怎么解耦行为」,前人总结成一套套可复用的套路——设计模式。比如「创建对象时不想让调用方关心具体类」用工厂、「多个对象要响应同一事件」用观察者、「想在不改原类的前提下加行为」用装饰器。GoF(Gang of Four)把 23 个经典模式分成创建型、结构型、行为型三类。本章入门这些模式解决什么问题、每类里有哪些代表、以及何时引入、何时别过度设计

一、设计模式解决什么问题

设计模式是在特定场景下、针对重复出现的设计问题的通用解决方案的抽象。它们不是具体代码,而是「怎么组织类与对象、怎么分工、怎么降低耦合」的套路,用统一的名字(如 Factory、Observer)方便沟通和查阅。模式通常包含:问题(要解决什么)、方案(参与角色与协作方式)、后果(优缺点与适用边界)。

模式的价值在于:复用经验——不用从零摸索;统一语言——说「这里用策略模式」大家就懂;指导扩展——按模式扩展比乱加 if-else 更稳。但模式是手段不是目的:只有在「这里确实有重复问题」时引入才有意义,否则容易变成为模式而模式的过度设计。

GoF 三类:创建型、结构型、行为型

二、GoF 分类概览

创建型(Creational)
关注对象的创建:谁造、怎么造、是否复用实例。把「new 具体类」从业务逻辑里抽离,便于扩展和测试。
工厂方法 Factory Method
抽象工厂 Abstract Factory
单例 Singleton
建造者 Builder
原型 Prototype

常见用法: 工厂——根据参数或配置返回具体产品,调用方只依赖抽象;单例——全局唯一实例(如配置、连接池),慎用、避免隐藏依赖。

结构型(Structural)
关注类与对象的组合:如何拼出更大结构、如何在不改原类的前提下扩展接口或职责。
适配器 Adapter
装饰器 Decorator
代理 Proxy
外观 Facade
桥接 Bridge
组合 Composite

常见用法: 适配器——把第三方接口「转」成己方接口;装饰器——包装对象,层层叠加行为(如日志、缓存),不修改原类。

行为型(Behavioral)
关注对象间的协作与责任分配:谁通知谁、算法如何切换、请求如何传递。
观察者 Observer
策略 Strategy
命令 Command
状态 State
责任链 Chain of Responsibility
模板方法 Template Method

常见用法: 观察者——主题状态变化时通知多个订阅者,解耦发布与订阅;策略——把算法封装成可替换的策略对象,运行时切换。

几个代表模式一句话

左:观察者(Subject 通知多个 Observer);下:策略(Context 依赖 Strategy 接口,可替换实现)

三、何时引入模式、何时避免过度设计

模式是工具箱里的工具:问题对上了再用。若没有「多实现要切换」「多订阅者要通知」「接口不兼容要包装」等需求,不必强行上工厂、观察者、适配器。过度设计的表现:为了「用上模式」而拆出一堆只有一处调用的抽象、或每个类都套一层工厂,导致阅读和维护成本上升。

适合引入模式的时机

  • 同一类问题反复出现(如多处需要「按类型创建」→ 工厂)
  • 确实有多实现、要扩展(如多种支付方式 → 策略/工厂)
  • 要解耦「谁通知谁」(事件、消息 → 观察者)
  • 要对接老接口或第三方(接口不一致 → 适配器)
  • 要无侵入地加行为(日志、缓存 → 装饰器/代理)

避免过度设计

  • 只有一种实现、且短期不会变:不必先抽象再实现
  • 调用点只有一处:不必为「可能以后会多」提前上模式
  • 团队不熟悉该模式:先理解问题再引入,避免照抄结构
  • 简单 if-else 能说清:不必为了「优雅」强行策略/状态机
何时用模式、何时收手

建议:先写直白实现,在出现「改不动、重复多、要扩展」时再考虑对应模式;引入时指名「我们这里用 XX 模式」,便于沟通和文档化。

一句话: 设计模式是重复设计问题的通用解决方案,GoF 分为创建型(怎么造对象:工厂、单例等)、结构型(怎么拼结构:适配器、装饰器等)、行为型(怎么解耦行为:观察者、策略等)。在「问题确实存在、有多实现或要解耦」时引入;只有一种实现、不会扩展时不必为模式而模式,避免过度设计。

小贴士: 学模式时重点记「解决什么问题、参与角色有哪些、适用边界」;写代码时先想「这里疼在哪里」,再查有没有现成模式能缓解,而不是先想「这篇代码我要用哪个模式」。

四、小结

设计模式解决反复出现的设计问题,提供可复用的套路与统一命名。GoF 分三类:创建型(工厂、单例等)、结构型(适配器、装饰器等)、行为型(观察者、策略等)。代表模式如工厂封装创建、适配器统一接口、观察者解耦通知、策略封装可替换算法。应在「问题存在、要扩展或解耦」时引入,避免只有一种实现或单点调用时过度设计。下一章进入版本控制与 Git 工作流,把「怎么协作、怎么管理变更」落到实处。