22

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

自从我阅读了贫血域模型(我一直在做的事情)以来,我一直在努力摆脱创建只是“getter 和 setter”的域对象,并回到我的 OO 根源。

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

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

所以我们有一个团队,其中有一个球员名单:

public class Team {

    private List<Player> 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() 方法...

但是如果Player正在推动离开怎么办 - leaveTeam() 方法是否应该调用 team.removePlayer(this)?并非没有创建无限循环!

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

public class SomeService {

    public void leave(Player player, Team team) {

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

    }

}

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


感谢大家的回复。我接受Grodriguez的解决方案,因为它是最明显的(不敢相信我没有想到)并且易于实施。然而,DecaniBass确实提出了一个很好的观点。在我所描述的情况下,球员有可能离开球队(并注意他是否在球队中)以及推动球队撤离的球队。但我同意你的观点,我不喜欢这个过程有两个“入口点”。再次感谢。

4

4 回答 4

16

你可以通过添加守卫来打破循环依赖来检查球队是否还有球员/球员是否还在球队中。例如:

在课堂上Team

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

在课堂上Player

public void leaveTeam() {
    if (team != null)
    {
        team.removePlayer(this);
        team = null;
        // Do some more player stuff..
    }
}
于 2010-10-24T07:52:38.100 回答
8

本,

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

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

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

2 路引用(Parent -> Child 和 Child-> Parent)通常充满其他东西,比如垃圾收集、维护“引用完整性”等。

设计是一种妥协!

于 2010-10-24T08:15:51.973 回答
2

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

public class Team {

    private List<Player> 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();
    }

}
于 2010-10-24T08:03:17.563 回答
1
public void removePlayer(Player player) {
    if (players.contains(player)) {
        players.remove(player);
        player.leaveTeam();
    }
}

里面同上leaveTeam

于 2010-10-24T07:51:25.813 回答