假设我们有一个API。

interface Graph {
    boolean checkIfPathExists(source, destination);
    List<Integer> getPath(source, destination);
}


以下哪一项是最佳/推荐的实施方式。

选项1:强制检查以确认路径是否存在。如果没有提前调用checkPath,则抛出异常。

Graph g = new GraphImpl(graph);
if (g.checkIfPathExists(s, d)) {
   List path = g.getPath(s, d);
}


选项2:不强制执行功能序列。如果调用了getPath,则让getPath()内部调用checkIfPathExists(),如果checkIfPathExists()返回false,则返回空集合。

Graph g = new GraphImpl(graph);
List path = g.getPath(s, d);


我认为Option2对我来说不错,但唯一的问题是对“状态检查方法(如'checkIfPathExists()”)的重复/不必要的调用。理想情况下,这不是getPath()应该做的事情。它应该只是在返回路径。


哪个是更好的实现option1或option2?
如果option2是更好的选择,那么根本不添加“ checkIfPathExists”作为公共接口会是更好的设计选择吗?要提出一个问题,如果没有强制执行,则更通用的状态检查方法看起来像“ hasNext()”。即使要遍历列表,我们也可以获取列表的大小并使用for循环,直到i 简而言之-如果不执行状态检查功能,该怎么使用?
是否存在强制执行状态检查方法的“实际”示例?意思是,不将它们提前调用会导致异常吗?

最佳答案

是否具有仅用于“保护”对另一个函数的调用而存在的checkIfExistshasNext函数实际上取决于所保护函数的成本和后果。

如果getPath非常昂贵而checkIfPathExists非常快,则同时具有这两个功能是有意义的。但是,对checkIfPathExists之前的相同参数强制调用getPath并不常见,而且似乎是不必要的,因为如果您可以将该机制放入其中,那么您也可以缓存其结果,因此实际上无需在,请使用高速缓存(如果可用)或执行调用。

对于带有getPathIterator,其部分原因是对hasNext的调用会带来后果和未知的开销(可能是将数组中的任何内容循环到单链列表,再使用网络连接)。调用next后,您也无法返回,因此,如果处理当前元素的逻辑根据是否存在下一个元素而改变,则Iterator需要支持它。

如果您特别担心性能,则可以提供两种方法,一种假定路径确实存在(next已被调用并返回true),因此不需要执行存在性检查,而另一种则不进行这种假设。并在搜索前调用checkIfPathExists。在javadoc中适当地记录方法,用户通常会正确使用它们。

要直接回答您的问题,通常会首选选项2,因为它更可取,并且不需要额外的代码复杂性即可验证调用顺序。规定了首先调用checkIfPathExists的优点(如果存在)的文档足以解决此选项的所有问题。

09-27 05:18