首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >OO设计和循环依赖

OO设计和循环依赖
EN

Stack Overflow用户
提问于 2010-10-24 15:45:59
回答 4查看 4.2K关注 0票数 22

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

自从我读到Anemic Domain Model (我一直在做的事情)以来,我真的一直在努力摆脱创建域对象,这些对象只是“大量的getter和setter”,并返回到我的OO根。

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

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

所以我们有一个团队,它有一个球员列表:

代码语言:javascript
复制
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,它引用了球队:

代码语言:javascript
复制
public class Player {
    private Team team;

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

可以假设这两个方法(remove和leave)都有特定于域的逻辑,每当球队移除球员和球员离开球队时,都需要运行该逻辑。因此,我的第一个想法是,当Team踢到一个球员时,removePlayer(...)还应该调用player.leaveTeam()方法...

但是,如果播放器驱动了变化- leaveTeam()方法是否应该调用team.removePlayer(this)呢?如果不创建无限循环,就不会!

在过去的中,我只是让这些对象成为“哑巴”POJO,并让一个服务层来做这项工作。但即使是现在,我仍然面临这个问题:为了避免循环依赖,服务层仍然将所有这些都链接在一起--即

代码语言:javascript
复制
public class SomeService {

    public void leave(Player player, Team team) {

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

    }

}

我是不是把事情搞得太复杂了?也许我遗漏了一些明显的设计缺陷。任何反馈都将非常感谢。

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-10-24 15:52:38

您可以通过添加后卫来检查球队是否仍有球员/球员是否仍在球队中,从而打破循环依赖。例如:

在类Team

代码语言:javascript
复制
public void removePlayer(Player player) {
    if (players.contains(player))
    {
        players.remove(player);
        player.leaveTeam();
        // Do other admin work when a player leaves
    }
}

在类Player

代码语言:javascript
复制
public void leaveTeam() {
    if (team != null)
    {
        team.removePlayer(this);
        team = null;
        // Do some more player stuff..
    }
}
票数 16
EN

Stack Overflow用户

发布于 2010-10-24 16:15:52

本,

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

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

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

双向引用(父->子和子->父)通常充满了其他东西,比如垃圾回收、维护“引用完整性”等。

设计是一种妥协!

票数 8
EN

Stack Overflow用户

发布于 2010-10-24 16:03:18

我的想法是在不同的方法中做领域相关的事情,这些方法彼此不调用,但为他们自己的对象做领域相关的事情,即团队的方法为团队做,球员的方法为球员做

代码语言:javascript
复制
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();
    }

}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4007451

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档