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);
}
}
}