这是循环依赖吗?

10

这段代码是否是循环依赖的示例?

package expr;
import sheet.Sheet
public class AdressExpr implements Expr
{
    private Address address; 
    private Sheet sheet; 
    public double value(Sheet sheet)
    {
        return sheet.value(address);
    }
}
public interface Expr
{
    public double value(Sheet sheet);
}
public class Adress
{
    // omissions
}

package sheet; 
import expr.Address; 
import expr.Expr;

public class Sheet implements SuperSheet
{
    private Map <Address, Expr> map; 
    public double value(Address address)
    {
    return map.get(Address).value(this);
    }
}
public interface SuperSheet
{
    public double value(Address address);
}

我知道这个例子是糟糕的编程,但是由于value方法的存在,接口是否禁止循环依赖关系?

3个回答

6
我认为在类图中更容易看出来。正如您所见,Sheet具体类和Expr接口之间确实存在循环依赖关系。我不会说这是非常糟糕的,因为我认为两个具体类之间的循环依赖关系是最糟糕的... 也就是说,如果可能的话,这样做肯定不可取。 你的代码 enter image description here 因此,也许你可以考虑重构的一种方式是让你的AddressExpr依赖于SuperSheet而不是Sheet,并且让Expr依赖于SuperSheet而不是Sheet:-
public class AdressExpr implements Expr {
    private Address address;
    private SuperSheet  sheet;

    public double value(SuperSheet sheet) {
        return sheet.value(address);
    }
}

public interface Expr {
    public double value(SuperSheet sheet);
}

...
...

...并且这将消除任何不需要的循环依赖。

可能重构的代码

enter image description here

注意:我并不是在暗示这就是解决方案。我只是说你可以尝试重构你的代码来最小化或者消除循环依赖,因为循环依赖会让你的代码难以进行单元测试。针对接口编码总是有助于消除不必要的循环依赖。它还使你的代码更容易进行单元测试,因为你可以轻松地模拟对象。


1
那些类图看起来很不错。你用了什么工具来生成它们? - TheAmpersand

3

这是一个非常有趣的例子。我将详细说明我的思考过程,因为我怀疑命名可能有些愚蠢。

包: sheet expr

sheet的内容:

  • Sheet
  • SuperSheet

expr的内容:

  • AddressExpr
  • Expr
  • Address

每个内容的用法:

  • AddressExpr - Expr、Address、Sheet
  • Sheet - SuperSheet、Address

我们看到AddressExpr依赖于在sheet包中的Sheet。一条依赖关系已经确定。

我们还看到Sheet依赖于在expr包中的Address。

因此,sheet和expr包之间存在循环依赖关系。(注意:工具可以显示此内容。我手动完成了此操作,因为您的问题非常抽象。请查阅JDepend)

此外,我甚至不确定是否曾听说过值方法。如果编译器能够理解双向接口使用,那么它就可以正常工作。它有能力解决混乱的问题。


2
至少在包级别上,sheet包依赖于expr包,反之亦然。基于个人经验-我会重构这个。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接