学习笔记 ---- 设计模式之策略模式
Joe面对的问题是:鸭子的行为在子类里持续不断的改变,每次升级增加新的子类,不同的子类都要重写积累中这些变化的行为,
麻烦并且混乱,所以让所有的子类都拥有基类的行为是不合适的;而使用文章中接口的方式,当有多个子类时,接口中任何一个方法的改变,
必须重复修改所有子类中的方法,又破坏了代码的重用。
软件开发过程中恒定不变的 是变化本身,所以直面“变化这个事实”才是正道。
第一个设计原则:Identify the aspects of your application that vary and separate them from what stays the same.(找到系统中变化的部分,将变化的部分同其它稳定的部分隔开)。也即:把变化的部分找出来并封装起来,以便以后可以轻易地改动或者扩展此部分,而不影响其他变化的部分。这样,代码变化引起的不经意后果减少,系统变得更具有弹性。
第二个设计原则:Program to an interface, not an implementation.(面向接口编程,而不要面向实现编程。)在本例中,也即提用两个接口代表每个行为,而行为的每个实现(行为类),都将实现对应的接口。
这与我们以前的做法不同,以前的做法是:行为来自超类的具体实现,或是继承某个接口并由子类自行实现。这两种方法都依赖于“实现”。我们现在的做法是:鸭子的子类将使用接口所表示的行为,所以实际的“实现”不会被绑死在鸭子的子类里。
Strategy Class Diagram
Context(应用上下文):
需要使用ConcreteStrategy提供的算法。
内部维护一个Strategy的实例。
负责动态设置运行时Strategy具体的实现算法。
负责跟Strategy之间的交互和数据传递。
Strategy(抽象策略类):
定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,Context使用这个接口调用不同的算法,一般使用接口或抽象类实现。
ConcreteStrategy(具体策略类):
实现了Strategy定义的接口,提供具体的算法实现。
应用场景:
多个类只有在算法或者行为上稍有不同(多个ConcreteStrategy)
算法需要自由切换的场景,或者未来还可以扩展新的算法或行为
需要屏蔽算法规则的场景,例如,Duck与具体的算法完全独立
模式优点:
提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更灵活(算法独立,可以任意扩展)。
避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
模式缺点:
策略类数量会增多
策略类均对外暴露
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决