当前位置: 首页 > 面试题库 >

OO设计和循环依赖

帅雅逸
2023-03-14
问题内容

我目前在设计类时遇到循环依赖问题。

自从我了解Anemic域模型(我一直在做的事情)以来,我一直在努力摆脱创建仅仅是“
getter和setter的存储桶”的域对象,并回到我的OO根。

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

假设我们有一个 Team 类,其中有很多 Player
。这是什么运动都没有关系:)球队可以添加和删除球员,就像球员离开球队并加入另一个球队一样。

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

public class Team {

    private List<Player> players;

    // snip.

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

然后我们有了玩家,该玩家可以参考团队:

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
确实很不错。在我描述的情况下,玩家可能会离开团队(并知道他是否在团队中)以及推动移除的团队。但是我同意你的观点,并且我不赞成在此过程中有两个“入口点”的想法。再次感谢。


问题答案:

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

在课堂上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..
    }
}


 类似资料:
  • 我在客户机-服务器体系结构中使用协议缓冲区作为有线数据格式。域对象(JavaBeans)将经历以下生命周期。 用于客户端业务逻辑 转换为协议格式 传送到服务器 转换回域对象 用于服务器端业务逻辑 “协议缓冲器和O-O设计”部分在协议留档中建议在适当的域模型内包装生成的类。 我想找出最好的办法。 例如,我有一个简单的原型定义。 这就是域模型的定义方式。如您所见,数据完全存储在proto builde

  • 问题内容: 所以我上了课: 我想让它的可读版本显示在网格列中。 什么是实现此目的的最佳和简洁的方法? 类内部的方法( 我个人不喜欢这种方法,因为’toString’与Address没有直接关系 ) 类 ( ) 上市 上一类,但将是静态的,接收实例并返回字符串 其他?请提出建议。 我正在寻找一个好的设计,同时还要关注“ 干净代码” ,“ 去耦” 和“ 可维护性” 。 问题答案: 所有这些方法均已使用

  • 问题内容: 简要阅读以上文章后,我发现getter和setter是糟糕的OO设计,应避免使用它们,因为它们与封装和数据隐藏相反。在这种情况下,创建对象时如何避免这种情况,以及如何将一个模型对象考虑在内。 如果需要使用吸气剂或吸气剂,还可以使用其他替代方法吗? 谢谢。 问题答案: 吸气或吸气器本身并不是很糟糕的OO设计。 不好的是编码实践,它会自动为每个单个成员包括一个getter和一个setter

  • 问题内容: 我有一个模块化的maven项目,其中两个模块“ BIZ”和“ EJB”包含如下内容: 如您所见, “ EJB”依赖于“ BIZ”, 因为它使用 MyClassX (实际上,它使用了BIZ的几种类别)。这就是 ImplFactory 使用反射实例化 InterfaceImpl 的原因。问题是 cl.newInstance() 将抛出 ClassCastException, 因为这两个模块

  • 问题内容: 我是一个长期的python开发人员。我正在尝试Go,将现有的python应用程序转换为Go。它是模块化的,对我来说真的很好用。 在Go中创建相同的结构后,我似乎陷入了周期性的导入错误,这比我想要的要多得多。从未在python中出现任何导入问题。我什至不必使用导入别名。所以我可能有一些在python中不明显的周期性导入。我实际上发现那个奇怪。 无论如何,我迷路了,试图在Go中修复这些问题

  • 在循环一节,我们已经讨论了 Python 基本的循环语法。这一节,我们将接触更加灵活的循环方式。 range() 在Python中,for循环后的in跟随一个序列的话,循环每次使用的序列元素,而不是序列的下标。 之前我们已经使用过range()来控制for循环。现在,我们继续开发range的功能,以实现下标对循环的控制: S = 'abcdefghijk' for i in range(0,len