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
里面。