面向对象设计,定义关系

时间:2010-11-08 02:25:28

标签: oop design-patterns

在设计相对较大的系统时,我对OOD非常困惑。总是,我们谈论两个实体之间的关系。我的问题是关于哪一个拥有另一个?

  1. 在设计停车场时,有很多停车位。汽车是否应该有一个称为停车位的数据字段,或者停车位是否应该停放汽车?或两者兼而有之?

  2. 在图书馆预订系统中,我假设有一个类库,一个类Book和一个类User。用户应该拨打结账(预订),还是图书通话结账(用户),还是图书馆通话结账(图书,用户)?

  3. 这对我来说非常困惑。欢迎任何评论/建议。

    百合

5 个答案:

答案 0 :(得分:2)

这取决于具体情况,以及“你自己”的意思。

在您的第一个示例中,汽车和停车位之间存在一对一的关系。从数据库的角度来看,你将不得不判断哪个应该“拥有”另一个(哪个表'拥有'外键)。你可以根据预期的使用情况做出判断 - 例如 - 由于停车位可能会保持固定,但是你的车辆一直都在进出,因此停车场“拥有”这辆车可能更合乎逻辑。这就是你的设计技巧发挥作用的地方。

在第二个例子中,在我看来,一本书只能一次签出给一个用户,而“签出”是一本书上发生的动作。因此,正确的解决方案是Book.checkout(user)。在此基础上,用户可能会一次签出多本书,因此我倾向于在库上设置结帐方法,以便Library.checkout(Books[], user)依次调用Book.checkout(user)

答案 1 :(得分:1)

对于#1,停车位应该记录它是否被占用,如果是,它是什么车。否则,为了看看你是否可以在某个地方停车,你必须对每辆车进行轮询,看看他们是否在那个地方。

我对#2的直接思考是,它应该是Library.checkout(Book, User),以便您记下用户已签出特定图书。

这在很大程度上取决于您尝试做的事情,而且您应该以最容易解决问题的方式进行设计。

有时在两个地方复制数据并不是一个糟糕的想法,只要你保持同步。例如,如果您需要知道特定车辆的停放位置,您最终还是希望在Car级别中跟踪这些数据,否则您将不得不每次轮询停车位,知道那辆车是否停在那里。

答案 2 :(得分:0)

在面向对象的设计中,对象可以被视为实体。此时,您可以使用实体关系建模来更好地了解谁拥有什么。

当您设计模型时,您不应该关心如何实现它。我的意思是你不应该想到谁会拥有什么,因为这是设计的另一个过程,当你要将模型转换为对象(可以是数据表,XML,C#对象,......)时:在这一点上反对实体得到的关系你可以决定谁拥有什么(有时甚至违反要求,我稍后会告诉你)。 在设计时,您必须只关注您的要求。在汽车和停车场的情况下,您应该考虑:

一辆公园车可以占用多少?

公园可以容纳多少辆汽车?

我的系统有什么样的答案可以回答? EX:作为用户我想知道车停在车牌号码的哪个地方(在这种情况下,之前的答案是错误的,因为如果你让公园拥有车,你应该在公园内迭代以获得车上的车辆)

正如您所看到的,它实际上取决于您的业务需求,尤其是当您具有“一对一”关系时(如本案例所示)。

所以我建议你看看“实体关系建模”并坚持其概念,以更好地设计你的对象模型。

答案 3 :(得分:0)

  1. 在这种情况下,无疑停车位应该是一辆汽车(称为聚合),因为汽车和停车位之间的关系不是永久性的(不同的汽车可以在同一天停放在同一个停车位)

  2. 在这种情况下,我认为,用户想要获得一本书,因此该系统的GUI必须有一些按钮(或其他),用户必须单击该按钮才能预订一本书。因此,用户调用系统的方法checkout(book)(对象库代表它)来检查该书是否空闲(或可用)。然后系统(库)检查该书是否未被其他用户提前保留,因此它为本书的所有实例调用方法Book.check()。在此类解决方案中,系统中的每个用户帐户都应该有一个方法Book.check()使用的保留书籍列表。

答案 4 :(得分:0)

为了开箱即用,我不认为你提供的例子有一个自然的"有一个"或者"拥有一个"关系,并且有更多的关系而不是"有一个"或者"拥有一个"。在我看来,我想为你的例子使用一个松散耦合的关系,在实现的角度来看,我会用一张地图来描述和维护这种关系,这意味着,对于一个停车场和一辆汽车,我会把停车类中的地图,并将其插槽映射到汽车,如果我们发现地图中存在插槽,我们知道插槽已被占用,如果没有,则它是一个空闲插槽,对我而言,它不会。无论是说汽车拥有插槽还是插槽拥有汽车都有意义;对于图书馆的例子,同样的事情,这本书及其借款人处于一种非常松散的关系中,我将图书放在图书馆课堂上,并将图书映射到其借款人。那个人真正做结账行动的人是谁?它既可以是图书馆工作人员,也可以是自动机器,也可以只是图书馆,因此我们可以拥有一个library.checkout(用户,书籍),并在方法内部将书籍和用户放入地图中。

对于奖金,真正的"有一个"关系情景?不是一个男人有车,这不是一个真正的"有一个",即使我们有"有一个"在句子中(不要让人类语言误导你),这只是意味着,在汽车的类中,有一个名为ownerName或ownerId的字符串字段,就是它。真实"的一个例子是"关系场景是人类有一颗心或一辆汽车有一个引擎,这意味着,在实现中,人类中确实存在一个Heart类字段。

面向对象设计的美妙程度!