设计模式二刷*
同样是对依赖的对象的增强,什么时候用装饰模式,什么时候用代理模式
技术面上操作:关注被增强的对象是否期望 对调用方保持透明,装饰模式保持被增强对象的透明,代理模式则更强调控制和隐藏。
deepseek给了一个总结:
代理模式:
隐藏被代理对象,控制访问(如延迟、远程、安全)。
调用方通常不感知代理背后的细节。
装饰模式:
透明增强对象功能,支持多层叠加。
调用方通常知道被装饰对象的存在。
最终决策依据:
如果目的是管控访问(隐藏对象、控制生命周期、权限)→ 代理模式。
如果目的是灵活叠加功能(透明增强)→ 装饰模式。
即使代码结构相似,设计意图才是选择模式的核心标准!
即使代码结构相似,设计意图才是选择模式的核心标准!
策略模式好像没有解决什么问题,只是简单的用单一职责的理念 将算法抽象成类,有什么特殊的吗?context是关键吗,如果我直接new 不同的算法直接pay呢?
策略模式的真正解耦点
即使客户端需要 new 具体策略类,以下解耦依然存在:
上下文类(PaymentContext)的稳定性:
无论策略如何变化,PaymentContext 的代码无需修改(符合开闭原则)。
客户端业务逻辑的隔离性:
支付金额计算、订单处理等逻辑只需调用 context.executePayment(),与支付方式无关。
测试的便利性:
可以轻松用Mock策略替换真实实现,方便单元测试。
5. 总结:何时算真正解耦?
场景 耦合程度 解决方案
客户端直接 new 策略类 部分解耦(依赖接口,但需知具体类) 示例代码中的基础策略模式
客户端通过工厂获取策略 高度解耦(仅依赖工厂和接口) 工厂模式 + 策略模式
客户端通过DI容器获取策略 完全解耦(零感知具体类) Spring等依赖注入框架
策略模式的价值在于提供行为扩展的灵活性,而完全解耦需要与其他模式(如工厂、DI)配合。在实际项目中,策略模式很少单独使用,而是作为更大设计的一部分
工厂模式和简单工厂如何选择?
维度 工厂模式(简单工厂) 工厂方法模式
定义 一个工厂类统一创建所有产品 每个产品对应一个工厂子类,由子类决定实例化哪个产品
设计模式分类 不属于GoF 23种设计模式(更像编程习惯) GoF 创建型模式
扩展性 新增产品需修改工厂类(违反开闭原则) 新增产品只需新增工厂子类(符合开闭原则)
复杂度 简单,适合产品类型固定的场景 稍复杂,适合产品类型频繁扩展的场景
典型应用 JDK 的 Calendar.getInstance() Spring 的 BeanFactory
总结
简单工厂:代码简单,但扩展性差,适合稳定场景。
工厂方法:扩展性强,符合开闭原则,适合复杂系统。
终极建议:
如果是工具类、配置类等简单创建,用工厂模式。
如果是业务核心组件(如支付、日志),用工厂方法模式。
记住:工厂方法模式是简单工厂的“升级版”,在大型项目中优先使用后者。
外观模式对比代理模式
关键区别总结
维度 外观模式 代理模式
主要目标 简化子系统调用 控制对单个对象的访问
接口关系 定义新接口(不强制与子系统一致) 实现与真实对象相同的接口
对象数量 封装多个子系统 通常代理一个对象
客户端感知 知道外观类的存在 可能不知道代理的存在(如动态代理)
典型应用 封装微服务调用、API 网关 延迟加载(Hibernate)、AOP、RPC
总结
外观模式是“简化复杂系统”,代理模式是“控制对象访问”。
外观模式关注宏观整合,代理模式关注微观增强。
两者均可降低耦合,但解决不同层次的问题。
一句话记忆:
外观模式是“一站式服务”,代理模式是“权限管家”。
建造者模式使用场景
- 对象的属性非常多
- 有固定不同的若干实例化类型
从未用过的模式但可能实用的模式
建造者模式(可选属性多且存在固定几种选择)
状态模式(状态固定,自流转,外部不感知内部状态)
责任链模式(职责固定,外部明确感知内部职责且执行过程由外部指定)
装饰模式(之前与代理搅在一起,外部感知被装饰类)
工厂方法模式(生产对象规则不固定,需要频繁违反开闭原则变更工厂类)
备忘录模式(b端的一致性场景,要思考如何在分布式场景下做优化)
解释器模式(处理自定义表达式)
从未用过且不实用(实用场景很难碰到-踢出内存)
抽象工厂模式(产生一系列由多套实现的对象)
适配器模式(设计目标强调兼容历史接口)
组合模式(树)
中介模式(有利有弊,中介类违反开闭且会随着依赖类增长,越来约复杂,难以维护容易出错)
访问者模式(算法与数据结构分离,新增算法容易,新增数据结构较复杂)
用过但未察觉(剔出内存)
1. 外观模式(mvc,基本操作)
2. 观察者模式(分布式环境下消息取而代之,纯内存的观察者场景不多)
3. 迭代器模式(生产太少了,语言特性用的多)
4. 单例模式(双重锁定)
5. 享元模式(字典)