开放/封闭原则 OO 类设计
Posted
技术标签:
【中文标题】开放/封闭原则 OO 类设计【英文标题】:Open/Closed Principle OO class design 【发布时间】:2014-09-20 14:10:56 【问题描述】:我正在尝试为在加权图上运行的库找出类设计。可以在这个图上执行各种算法,例如,找到两个节点之间的最短距离、两个节点之间的最长距离、两个节点之间距离小于 10(比方说)的路径数等。
我关心的不是如何实现图表的算法或数据结构,因为我知道如何做到这一点,而是整体高级类设计。关键是将来我们可能希望添加其他算法,因此该解决方案应该易于扩展。实现的一种选择是只编写一个类,该类具有实现这些算法中的每一个的方法。然后,将来可以为此类添加其他方法以用于任何新算法。
public class GraphCalculator
Graph _graph;
public int GetLongestDistance(string startPlaceName, string endPlaceName)
public int GetShortestDistance(string startPlaceName, string endPlaceName)
public int GetNumberOfPaths(int minimumDistance)
//any new algorithms will be implemented as new methods added to this class
我担心这违反了 SOLID 开/关原则。每个算法是否应该在其自己的类中实现?如果是这样,实现这一点的推荐类结构是什么,以便松散耦合且易于测试,以及如何从公共 API 层调用它?有什么推荐的设计模式吗?
【问题讨论】:
附注:GetLongestDistance
方法之一应重命名为 GetShortestDistance
。
【参考方案1】:
您的问题的答案是否应该在自己的类中实现每个算法绝对是是的!您说的是,您想要易于扩展 的解决方案。 具有实现这些算法的方法的单个类。然后在未来可以为任何新算法添加额外的方法到这个类中。它根本不可扩展!您正在更改代码,您需要修改您当前的基本实现!这与 OOP 原则完全相反——对修改关闭,对扩展开放!
您必须(现在或将来)实现的每一个算法都是一种行为,应该使用接口来定义。所有的实现都应该实现这个通用接口。这样,您还可以轻松地自行测试每个算法的实现。这还允许您定义一个算法列表,可以轻松地动态维护(通过代码或配置)。考虑到这一切,您需要的是某种插件架构。
Visitor pattern 可能是满足您需求的一种设计模式,因为它向现有数据结构(图形对象)添加了新操作(= 最短路径、最长路径等算法)。
另一个选项可能是PlugIn design pattern,尽管在 IMO 实施此模式可能比访问者更具挑战性。如果可以使用 3th 方软件和现有框架,您可以查看 Sprint plugin project,它使用 Spring 框架并定义了一个可插入架构助手。 .NET 的(有点)类似的解决方案是Managed Extensibility Framework 和/或Enterprise Library - Unity Application Block。
【讨论】:
【参考方案2】:为什么它必须以自己的class
开头?它本身并没有做任何有用的事情,只是包装了Graph
实例,并且知道它所提供的只是Graph
上的函数。您是否考虑过在一个辅助类中将它们设为static
函数,所有相关参数都被传递到该类中?
或者,如果您想让实现可互换,您可以考虑使用Strategy Pattern。
【讨论】:
它有自己的类,因为它应该是可以被某些客户端代码使用的 API/库。我不希望 API 的用户接触到内部图形结构,因此他们不应该将此信息传递给 API。我猜他们可以传入将要从中加载图形数据的数据存储位置。然后,API 实现将负责将此数据加载到 Graph 对象中。所以我真的不应该传入节点参数,而是传入节点的标识符(例如,如果每个节点代表一个地方,则为地名)。 我确实考虑过策略模式,但我真的不想让算法实现可互换,只是可扩展(通过添加新算法)。所以我想将它们放在单独的类中,但不确定策略模式是否涵盖这种特定场景。 策略模式在这种情况下不适合 - 它用于交换而不是扩展。以上是关于开放/封闭原则 OO 类设计的主要内容,如果未能解决你的问题,请参考以下文章