OO设计和循环依赖

在设计我的类时,我目前正在努力解决循环依赖问题。

自从我读到有关贫血领域模型 (我一直在做的事情)以来,我一直在努力摆脱创建只是“吸气剂和孵化器”的域对象并回到我的OO根源。

但是,下面的问题是我经常遇到的问题,我不知道应该如何解决它。

假设我们有一个Team类,它有很多玩家 。 这是什么运动并不重要:)球队可以添加和删除球员,就像球员离开球队并加入另一球员一样。

所以我们有一个团队,其中有一个玩家列表:

public class Team { private List players; // snip. public void removePlayer(Player player) { players.remove(player); // Do other admin work when a player leaves } } 

然后我们有了Player,它引用了Team:

 public class Player { private Team team; public void leaveTeam() { team = null; // Do some more player stuff... } } 

可以假设两种方法(删除和离开)都具有特定于域的逻辑,只要团队移除玩家并且玩家离开团队就需要运行这些逻辑。 因此,我首先想到的是当一个团队踢一个玩家时,removePlayer(…)也应该调用player.leaveTeam()方法……

但是如果播放器正在推动离开 – 如果leaveTeam()方法调用team.removePlayer(this)该怎么办? 不是没有创造无限循环!

在过去 ,我刚刚让这些对象“愚蠢”的POJO并让服务层完成工作。 但即使是现在我仍然存在这个问题:为了避免循环依赖,服务层仍然将它们连接在一起 – 即

 public class SomeService { public void leave(Player player, Team team) { team.removePlayer(player); player.leaveTeam(); } } 

我复杂化了吗? 也许我错过了一些明显的设计缺陷。 任何反馈将不胜感激。


谢谢大家的回复。 我接受Grodriguez的解决方案,因为它是最明显的(不能相信它没有发生在我身上)并且易于实现。 然而, DecaniBass确实提出了一个很好的观点。 在我描述的情况下,玩家可以离开一个团队(并且知道他是否在团队中)以及驱动移除的团队。 但我同意你的观点,我不喜欢这个过程有两个“切入点”的想法。 再次感谢。

您可以通过添加防守来打破循环依赖关系,以检查球队是否还有球员/球员仍然在球队中。 例如:

在class级Team

 public void removePlayer(Player player) { if (players.contains(player)) { players.remove(player); player.leaveTeam(); // Do other admin work when a player leaves } } 

在课堂上:

 public void leaveTeam() { if (team != null) { team.removePlayer(this); team = null; // Do some more player stuff.. } } 

本,

我首先会问一个玩家是否可以(合乎逻辑地,合法地)将自己从团队中移除。 我会说玩家对象不知道他在哪个团队(!),他是团队的一员。 因此,删除Player#leaveTeam()并通过Team#removePlayer()方法进行所有团队更改。

如果您只有一个玩家并且需要将其从团队中移除,那么您可以在Team public static Team findTeam( Player player ) ...上拥有静态查找方法public static Team findTeam( Player player ) ...

我知道这比Player#leaveTeam()方法更不令人满意和自然,但根据我的经验,你仍然可以拥有一个有意义的领域模型。

2种方式参考(父母 – >儿童和儿童 – >父母)经常充满其他东西,比如垃圾收集,保持“参照完整性”等。

设计是妥协!

想法是用不同方法做域相关的东西,这些方法不会互相调用,而是为自己的对象做域相关的东西,即团队的方法为团队做,而玩家的方法为玩家做

 public class Team { private List players; public void removePlayer(Player player) { removePlayerFromTeam(player); player.removeFromTeam(); } public void removePlayerFromTeam(Player player) { players.remove(player); //domain stuff } } public class Player { private Team team; public void removeFromTeam() { team = null; //domain stuff } public void leaveTeam() { team.removePlayerFromTeam(this); removeFromTeam(); } } 
 public void removePlayer(Player player) { if (players.contains(player)) { players.remove(player); player.leaveTeam(); } } 

同样在leaveTeam里面。