开放/封闭原则OO类设计

本文关键字:OO 原则 开放 | 更新日期: 2023-09-27 18:22:51

我正试图为一个在加权图上操作的库设计一个类。可以在该图上执行各种算法,例如,找到两个节点之间的最短距离、两个节点间的最长距离、距离小于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层调用它?有什么推荐的设计模式吗?

开放/封闭原则OO类设计

您的问题的答案是否每个算法都应该在自己的类中实现肯定是!您正在声明,您想要易于扩展的解决方案。一个单独的类,它有实现这些算法的方法。然后,在未来,可以为任何新算法向此类添加额外的方法它根本不可扩展!您正在更改代码,需要修改当前的基本实现!这与OOP原理正好相反——修改时关闭,扩展时打开!

你必须实现的每一个算法(现在或将来)都是一种行为,应该使用接口来定义。所有实现都应该实现这个通用接口。通过这种方式,您还可以轻松地测试每一个单独的算法实现。这还允许您定义一个算法列表,该列表可以很容易地动态维护(通过代码或配置)。考虑到所有这些,您需要的是某种插件体系结构。

一种符合您需求的设计模式可能是Visitor模式,因为它向现有的数据结构(图形对象)添加了新的操作(=最短路径、最长路径等算法)。

另一种选择可能是插件设计模式,尽管IMO这种模式可能比访问者更难实现。如果可以使用第三方软件和现有框架,您可以看看Sprint插件项目,该项目使用Spring框架并定义了可插拔架构助手。.NET的一个(有点)类似的解决方案是托管可扩展性框架和/或企业库-统一应用程序块。

为什么一开始就必须有自己的class?它本身并没有做任何有用的事情,只是包装了Graph实例,然后才知道它所提供的只是Graph上的函数。您是否考虑过将它们作为static函数放在一个助手类中,而将所有相关参数都传递到该类中?

或者,如果您想使实现可交换,您可能会考虑策略模式。