gpt4 book ai didi

java - 循环依赖设计

转载 作者:行者123 更新时间:2023-12-02 19:49:06 25 4
gpt4 key购买 nike

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

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

让我们举一个例子,我们想要表示房间的可变拓扑,其中 neighbour 具有自反属性

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,这显然是无休止的递归。但接下来我有几个选择:

  • 让一个 Room 拥有另一个 Room,以某种方式记录事实,然后只有一种类型的 Room 具有删除 功能。
  • 创建第二个方法removeSelf,它永远不会调用另一个Room的方法,从而解决无限递归问题。
  • 在层次结构中拥有一个较高的 Building 对象,并让它执行 Room 上的所有操作

它们各自的缺点是

  • 非常违反直觉,并且在不存在的情况下强加了一个人为的结构。此外,某个邻居中必须存在至少一个拥有的房间
  • 添加了一个用户永远不应该调用的方法,这作为一个接口(interface)很糟糕。
  • 需要一个拥有的对象,有时也是一个非常尴尬的结构,建筑物只是巧合地适合成为一个拥有的对象。

那么问题来了,如果循环依赖在某种程度上不可避免,那么更好的设计是什么?

我们或许可以创建一个 RoomOperator 类,其中包含对 Room 进行操作的函数,但它也会遇到与 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);
}
}

方法removeOther(Room r)告诉房间只从其列表中删除提供的房间。这与 remove(Room r) 方法相反,后者也会导致房间要求提供的房间将其删除。

如果接口(interface)方法很重要,那么该解决方案会保持接口(interface)方法的完整性。实际上,我会让各个房间扩展一个 AbstractRoom 类,并在其中添加两种方法的实现。但由于您指定的两个房间是相同的,因此很难知道到底要做什么。

如果您可以将方法更改为remove(Room r, booleancallback),您可以避免一些困惑并仅使用该方法。

为了方便使用,我还将 neighbours 更改为列表。

解决方案2

使用外部管理器(实用程序)类。该类允许消除房间相互管理的需要。

interface Room {
void remove(Room r);

List<Room> getNeighbours();
}

class Living implements Room {

List<Room> neighbours;

@Override
public void remove(Room r) {
RoomManager.removeRooms(r, this);
}

@Override
public List<Room> getNeighbours() {
return neighbours;
}
}

class RoomManager {

static void removeRooms(Room r1, Room r2) {
r1.getNeighbours().remove(r2);
r2.getNeighbours().remove(r1);
}
}

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

关于java - 循环依赖设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43971700/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com