Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 循环依赖的设计_Java_Circular Dependency - Fatal编程技术网

Java 循环依赖的设计

Java 循环依赖的设计,java,circular-dependency,Java,Circular Dependency,这是一个关于如何更好地处理循环依赖的问题。让我先说一句,我认为循环依赖很少有必要,但代码是传给我的,我无能为力 假设在概念上平等的类上存在循环依赖,即它们之间没有明显的“拥有”关系。我如何优雅地处理它们 让我们举一个例子,我们想用邻居自反属性表示房间的可变拓扑 interface Room { public void remove(Room r); } class Living implements Room { Room[] neighbour; public voi

这是一个关于如何更好地处理循环依赖的问题。让我先说一句,我认为循环依赖很少有必要,但代码是传给我的,我无能为力

假设在概念上平等的类上存在循环依赖,即它们之间没有明显的“拥有”关系。我如何优雅地处理它们

让我们举一个例子,我们想用
邻居
自反属性表示房间的可变拓扑

interface Room {
    public void remove(Room r);
}

class Living implements Room {
    Room[] neighbour;
    public void remove(Room r) {/* implementation */}
}

class Dining implements Room {
    Room[] neighbour;
    public void remove(Room r) {/* implementation */}
}
现在,在
remove
的实现中,显然我们不能在另一个
Room
上调用
remove
,这显然是无止境的递归。但我还有几个选择:

  • 让一个
    房间
    拥有另一个,以某种方式记录事实,然后只有一种类型的
    房间
    具有
    删除
    功能
  • 创建第二个方法
    removeSelf
    ,它从不调用另一个
    Room
    的方法,从而解决无限递归问题
  • 建筑
    对象放在层次结构的更高位置,并让它在
    房间
它们各自的缺点是

  • 非常违反直觉,在没有结构时强加人工结构。此外,在某个邻居中必须至少存在一个拥有
    房间的
  • 添加了一个不应该被用户调用的方法,这就像一个接口一样糟糕
  • 需要一个拥有对象,有时也是一个非常笨拙的结构,
    建筑
    恰好适合作为拥有对象
那么,问题是,如果循环依赖不可避免,那么什么是更好的设计呢

我们可能会创建一个
RoomOperator
类,其中包含要在
Room
s上操作的函数,但它也会遇到与上面的
removeSelf
方法相同的问题:它最终调用的方法在
RoomOperator
解决方案1之外是非法的 为房间添加功能,让他们知道是否需要请求邻居移除房间,从而避免递归

interface Room {
    void remove(Room r);

    void removeOther(Room r);
}

class Living implements Room {
    List<Room> neighbours;

    @Override
    public void remove(Room r) {
        r.removeOther(this);
        neighbours.remove(r);
    }

    @Override
    public void removeOther(Room r) {
        neighbours.remove(r);
    }
}

我再次向接口添加了一个方法,以便统一房间的组成。抽象类在这里会更好。

您可以添加一个基类
RoomSupport
,它管理所有依赖项。其他实现应该扩展
RoomSupport
。以下是实施情况:

abstract class RoomSupport implements Room {
    private final Set<Room> neighbours = new HashSet<>();

    @Override
    public void addNeighbour(Room r) {
        if (neighbours.add(r)) {
            r.addNeighbour(this);
        }
    }

    @Override
    public void remove(Room r) {
        if (neighbours.remove(r)) {
            r.remove(this);
        }
    }
}
抽象类RoomSupport实现了Room{
私有最终集邻居=新HashSet();
@凌驾
公共空间(r室){
若有(加(r)){
r、 (这个);
}
}
@凌驾
公共空间拆除(r室){
如果(删除(r)){
r、 移除(此);
}
}
}

实现会注意,添加和删除会终止,并且根本没有循环依赖关系。

您暗示了问题所在。正如您已经清楚地发现的那样,试图从单个对象的pov管理聚合属性(如“邻居”)是脆弱的。这是OO模型中容易出现的陷阱之一。这里的解决方案可能是实现一个
RoomManager
对象,它负责
房间
层次结构之外的
删除
等功能。希望您使用的是依赖项注入,因此可以根据需要注入。我认为需要另一个类来帮助您管理
Room
s,因为从Room中删除Room没有多大意义。是的,我在稍后的编辑中暗示了该解决方案,但让我烦恼的是,它最终在接口中调用了一个方法,除了
RoomManager
之外,不应该调用该方法,您可以更改什么?哪一部分是传给你的?
public
只是我懒惰:P编辑
abstract class RoomSupport implements Room {
    private final Set<Room> neighbours = new HashSet<>();

    @Override
    public void addNeighbour(Room r) {
        if (neighbours.add(r)) {
            r.addNeighbour(this);
        }
    }

    @Override
    public void remove(Room r) {
        if (neighbours.remove(r)) {
            r.remove(this);
        }
    }
}