这是一个关于如何更好地处理循环依赖的问题。让我在序言中说,我认为循环依赖很少有必要,但是代码是传给我的,我无法控制。
假设有一个循环依赖于具有概念上平等地位的类(它们之间没有明显的“拥有”关系)。我该如何优雅地处理它们?
让我们举一个例子,我们希望用自反属性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具有remove功能。removeSelf,它从不调用其他Room的方法,从而解决无限递归。Building对象,并让它执行Room上的所有操作它们各自的缺点是
Room的人必须存在于某个邻居的内部。Building只是巧合地适合作为一个拥有对象。那么,如果循环依赖在某种程度上是不可避免的,那么什么才是更好的设计呢?
我们可能会创建一个RoomOperator类,其中包含要在Room上操作的函数,但它也遇到了与上面的removeSelf方法相同的问题:它最终调用了一个在RoomOperator之外是非法的方法。
发布于 2017-05-15 05:39:22
解决方案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)方法形成了对比,后者还导致房间要求提供的房间移除它。
如果这一点很重要,这个解决方案将保持接口方法的完整。实际上,我会让不同的房间扩展一个AbstractRoom类,并在那里添加两个方法的实现。但是,由于两个给定的Room都是相同的,所以很难确切地知道该做什么。
如果可以将方法更改为remove(Room r, boolean callback),则可以省去一些混乱,只使用该方法。
为了便于使用,我还将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);
}
}再次,我在界面上添加了一种方法,以统一房间的组成。抽象类在这里会做得更好。
发布于 2017-05-15 05:41:21
您可以添加一个基类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);
}
}
}实现需要注意,添加和删除确实会终止,而且根本不存在循环依赖关系。
https://stackoverflow.com/questions/43971700
复制相似问题