结构型设计模式
本页按场景选择方法;通过各条目链接阅读完整推演、源码和输出。
各例是独立 main.go,需先创建模块再单独保存当前代码;本轮未执行。接口字段必须先提供有效实现,组合结构须有限无环且子节点非 nil;示例没有统一的空值防护或并发保证。外观中的 Save/Notify 是空实现,仅演示调用顺序,并未实际持久化或通知。
| 要解决的问题 | 可选方法 | 选择前确认 |
|---|---|---|
| 复用接口不匹配的旧代码 | 适配器 | 只负责接口与数据转换;示例保留错误传递,避免混入业务规则。 |
| 把常见的多步子系统调用收成一个入口 | 外观 | 减少调用方对步骤顺序的了解,同时保留特殊场景所需的底层能力。 |
| 在同一接口上叠加能力或限制访问 | 装饰器或代理 | 装饰器逐层添加行为且顺序有影响;代理控制转发,权限入口需避免绕过。 |
| 内容与呈现方式需要分别扩展 | 桥接 | 两个维度用接口连接,边界应对应真正独立变化的能力。 |
| 统一操作单个对象和递归对象树 | 组合 | 容器递归委托子节点;需定义空组、循环引用与错误传播。 |
| 大量对象重复保存相同配置 | 享元 | 共享内部状态应不可变;外部状态由各对象保存,并发缓存需同步。 |
接入旧接口并简化子系统入口
适配器
正文、推演与完整示例:适配器。
适配器应专注接口和数据转换,避免混入业务规则。
外观
正文、推演与完整示例:外观。
外观可以简化常见操作,但应保留必要的底层能力供特殊场景使用。
包装现有能力并控制访问
装饰器
正文、推演与完整示例:装饰器。
装饰器适合添加与核心任务正交的行为,但包装层过多会使调试路径变长。
代理
正文、推演与完整示例:代理。
同样的结构可用于缓存或延迟创建,但涉及权限时必须确保不存在绕过代理的直接入口。
让内容与渲染实现分别变化
桥接
正文、推演与完整示例:桥接。
接口边界应放在真正会独立变化的能力上。HTML.Render 仅演示组合,直接拼接固定教学文本;真实 HTML 输出含用户输入时必须进行上下文合适的转义,例如文本节点使用 html.EscapeString,或采用 html/template。
统一访问单个对象与对象树
组合
正文、推演与完整示例:组合。
设计递归结构时要决定空组、循环引用和错误传播应如何处理。
复用大量对象的不可变配置
享元
正文、推演与完整示例:享元。
被共享的 Style 应视为不可变;并发访问缓存时还需要同步保护。
静态自检
将桥接示例 Text 换成字面量 <script> 文本,当前 HTML.Render 会做转义吗?提示:只看 Render 的字符串拼接。
参考解法
不会;它只演示接口组合。真实文本节点必须转义或使用 html/template,不能把这个固定字符串例子当作安全 HTML 渲染器。
继续阅读
- 设计意图与对象责任
- 设计意图与对象责任
- 设计意图与对象责任