2010-04-11 148 views
7

当我为自己的项目构建自己的系统时,我正在学习很多关于设计模式的知识。我想问你一个我无法找到答案的设计问题。两个互相依赖的对象。那不好吗?

目前我正在使用带有多个客户端的套接字构建一个小型的聊天服务器。现在,我有三大类:

  1. 人级持有像尼克,年龄和房间对象的信息。
  2. 房间级别其中包含房间名称,主题和当前在该房间中的人员列表等信息。
  3. Hotel-class其中包含服务器上的人员列表和客房列表。

我已经做了示意图来说明吧:

我在酒店级服务器上的人员名单,因为这将是很好的跟踪有多少人在线现在(不必遍历所有房间)。 因为我希望能够在不搜索房间的情况下搜索特定人员,所以住在酒店级别的人。

这是不好的设计?有没有另外一种方法来实现它?

谢谢。

回答

4

的类之间的相互依存问题,严格来说,可以通过使用接口(抽象类,如果您的语言是例如C++或Python)IRoomIPerson来解决;在伪

interface IPerson 
    IRoom getRoom() 
    // etc 

interface IRoom 
    iter<IPerson> iterPerson() 
    // etc 

这使得只有接口互相依赖对方 - 实际实现的接口只需要取决于接口。

如果你想避免循环参考回路(这可能是一个麻烦,例如,在CPython中通过减慢垃圾回收) - 你可以使用弱引用,具有典型“一对多关系”表等的底层关系数据库等等。对于第一个简单的原型,你可以使用你选择的语言中最简单的原型(可能是简单的,并且必然是循环的,参考[C++中的指针]],参考RoomRoomlist<Person>Person

+1

我看到“相互依存”是我正在寻找的词。为了记录我正在用Java写这个。界面方法看起来很有趣,但并没有使解决方案变得更加不同,但我明白你的观点。感谢您的评论。 – 2010-04-11 03:10:29

+2

@Kasper,关键是,依赖于_interfaces_(包括相互之间)没有真正的问题 - 它主要依赖于您想要避免的_concrete_软件(例如,在“循环”的情况下)。自由开始一个快速而肮脏的实现并在稍后转向更加健全的实现,这也加快了软件原型设计和迭代的演变和维护。 – 2010-04-11 03:27:40

9

我不喜欢它。酒店包含客房,而客房则包含人。人们不包含房间,他们属于他们。

您不一定非得重复才能让您的客人数。您可以保留一个运行计数($ Hotel-> total_guests),并在更改时对其进行修改。

+0

我明白你的意思,我的逻辑存在缺陷,谢谢指出!然而,我的想法是,包含用户名和Person对象的HashMap在搜索用户方面比在迭代Rooms更快。 – 2010-04-11 02:57:30

+4

我完全赞赏你的欲望毫秒,因为我分享激情 - 但令人敬畏的OOP是关于更快/更干净的阅读和编写代码,而不是更快的执行时间。我建议你在两种方式和时间上尝试 - 差异可能不会像你想象的那么大。 (如果你这样做,请发布你的结果给我们!) – 2010-04-11 03:07:29

+0

你让我!关于欲望毫秒的评论很有用。你给了我一些想法,谢谢:) – 2010-04-11 03:17:18

1

在一个更大的系统中,这将会很糟糕,但是从我了解您的应用程序的情况来看,这三个类只能一起使用,这不算什么问题。只要确保以表明它包含对房间的引用而不是实例的方式来命名该人的成员变量。另外,除非出于性能方面的原因(例如,你将拥有大量的房间),否则可能会更清洁地制作一个将迭代房间并收集人员的属性或吸气器,而不是缓存它们酒店。

+0

为了记录,我同意将它们缓存为酒店的财产可能不是最好的方式去解决它。我个人也会迭代;) – 2010-04-11 02:53:27

+0

你会如何命名Person中的成员变量,所以它会更像是一个引用? 假设我有大量的用户,而且我需要搜索单个用户。什么是最好的方法?我知道我在参考文献中保留了冗余信息。这些类只能一起使用(还有几个,但不是很多)。 – 2010-04-11 03:03:54

0

相互依赖本身并不坏。有时数据使用需要它。

我以不同的方式思考它。维护一般具有较少关系的代码会更容易 - 相互依赖与否。尽量保持简单。在你创建和删除序列的过程中,你的情况唯一的额外技巧是有时会出现检查和蛋问题。你有更多的链接来保存图书。

如果您在询问这种情况下是否需要酒店的人员列表,我认为有两个答案。我会首先让您的对象(在内存中)提供这些关系,但是您不需要数据库中人员和酒店之间的额外连接表。如果你使用的是Hibernate,如果你问它为酒店的人(它会加入hotels.hotel_id上的酒店),它会自动生成一个有效的加入。