OO设计和循环依赖

Ben*_*n J 19 java oop circular-dependency

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

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

但是,下面的问题是我经常遇到的问题,我不确定应该如何解决它.

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

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

public class Team {

    private List<Player> players;

    // snip.

    public void removePlayer(Player player) {
        players.remove(player);
        // Do other admin work when a player leaves
    }
}
Run Code Online (Sandbox Code Playgroud)

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

public class Player {
    private Team team;

    public void leaveTeam() {
        team = null;
        // Do some more player stuff...
    }
}
Run Code Online (Sandbox Code Playgroud)

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

但是如果玩家正在推动出发 - 如果leaveTeam()方法调用team.removePlayer(this)该怎么办?不是没有创造无限循环!

在过去,我刚刚将这些对象设为"哑"POJO,并让服务层完成工作.但即使是现在我仍然存在这个问题:为了避免循环依赖,服务层仍然将它们连接在一起 - 即

public class SomeService {

    public void leave(Player player, Team team) {

        team.removePlayer(player);
        player.leaveTeam();

    }

}
Run Code Online (Sandbox Code Playgroud)

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


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

Gro*_*uez 14

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

在课堂上Team:

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

在课堂上Player:

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

  • 如果集合被更改,players.remove()将返回true; 不需要做.contains(). (5认同)
  • 可能只是我,但我喜欢尽可能地使用if ... else.我注意到它使代码的可维护性降低了一些 (2认同)
  • @Lie Ryan:多数人关系很多.建模的一种方法是找出一个具有来自玩家和团队的一对多关系的新逻辑实体.在当前示例中,它可能与存储玩家所参与的所有团队的历史数据相关.在这种情况下,它可能是"合同":-) (2认同)

Dav*_*err 8

本,

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

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

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

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

设计是妥协!