【问题标题】:Is this a Circular dependency?这是循环依赖吗?
【发布时间】:2011-02-14 13:44:20
【问题描述】:
这段代码是循环依赖的例子吗?
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 方法而禁止循环依赖吗?
【问题讨论】:
标签:
java
oop
circular-dependency
【解决方案1】:
我认为在类图中更容易看到。如您所见,Sheet 具体类和Expr 接口之间确实存在循环依赖关系。我不会说它非常很糟糕,因为我认为 2 个具体类之间的循环依赖是最糟糕的......也就是说,如果可能的话,当然不建议这样做。
您的代码
因此,也许您可能考虑重构的一种方法是让您的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);
}
...
...
...这将删除任何不需要的循环依赖。
可能的重构代码
注意:我并不是暗示这是解决方案。我只是说您当然可以考虑重构代码以最小化或删除循环依赖项的方法,因为循环依赖项会使您的代码难以进行单元测试。针对接口进行编码总是有助于消除不需要的循环依赖。它还使您的代码更容易进行单元测试,因为您可以轻松地模拟对象。
【解决方案2】:
这是一个非常时髦的例子。我将在这里非常详细地介绍我的思考过程,因为我怀疑这里有一些愚蠢的命名。
包:
床单
表达式
工作表内容:
expr 的内容:
各自的用法:
- AddressExpr - Expr、地址、工作表
- 工作表 - 超级工作表,地址
我们看到AddressExpr 依赖于Sheet,Sheet 位于sheet 包中。一个依赖关系下降。
我们还看到,Sheet 依赖于 expr 包中的 Address。
因此,您在 sheet 和 expr 包之间存在循环依赖关系。 (注意:工具可以显示这一点。我是手工完成的,因为您的问题非常抽象。查看 JDepend)
此外,我什至不确定我是否听说过价值方法。如果编译器可以理解双向接口的使用,它就会起作用。它有解开混乱的意义。
【解决方案3】:
至少在包装级别。包sheet 依赖于包expr,反之亦然。根据自己的经验 - 我会重构它。