共同的墙壁和旁边的房间之间有啥样的关系?

Posted

技术标签:

【中文标题】共同的墙壁和旁边的房间之间有啥样的关系?【英文标题】:what kind of relationship is there between a common wall and the rooms that located next to it?共同的墙壁和旁边的房间之间有什么样的关系? 【发布时间】:2012-06-29 11:25:04 【问题描述】:

我想知道公共墙(位于相邻房间)和房间之间的关系。 据我所知,房间与其墙壁之间的关系是Composition not Aggregation(我说的对吗?)

And according to the definition of 组合 the contained object can't be shared between two containers, whereas in 聚合 it is possible

现在我很困惑,什么是表示公共墙壁与其旁边房间之间关系的最佳建模方法?

如果您能提供一些代码的建议,将不胜感激。

|--------|--------|

方法 1:

(wall class ---- room class) /Composition

方法二:

wall class ----- room class /Aggregation

Approch3:

我们有一个墙类和一个公共墙类,公共墙类继承自墙类

adjoining room class ---- (1) Common wall class /Aggregation
adjoining room class ---- (6) wall class / composition

方法4: 我是开发人员而不是设计师 :) 所以这是我的想法:

class Room 

  private wall _firstwall  ;
  private wall _secondtwall;
  private wall _thirdwall  ; 
  private wall _commonwall ;

public Room( CommonWall commonwall)
 
 _firstwall=new Wall();
 _secondtwall=new Wall();
 _thirdwall=new Wall();
 _commonwall=commonwall;
 



Class CommonWall:Wall

 //...

// 在某个地方:

 static void main()

  Wall _commonWall=new Wall();
  Room room1=new Room(_commonWall);
  Room room2=new Room(_commonWall);
  Room [] adjacentRoom =new Room[2]room1,room2;

编辑 1: 我认为这是一个明确的问题,但只是为了进一步澄清:

问题的重点是找出对同时是两个其他对象的组件的对象的关系建模的最佳模式或方法。

关于我的例子:我的意思是“房间”吗?当然我指的是一个封闭的方形房间,有 4 面墙和一扇门。但在这种情况下,其中一堵墙是公共墙,由两个相邻的墙共用房间。

【问题讨论】:

我想我很困惑。在这种情况下,一个房间可以只有一面公共墙吗? 为什么它是组合还是聚合真的很重要? 适当的解决方案可能取决于您需要对数据执行的操作。是否涉及 RDBMS?通过多对多关系关联房间和墙壁?也许您只跟踪墙壁,并根据不同的墙壁集派生房间。普通墙是出现在多个集合中的墙吗?房间。墙壁;墙。房间;跟踪墙壁所属的所有父房间以及构成每个房间的所有墙壁。房间必须是封闭空间吗? 这个问题可能更适合programmers.stackexchange.com,因为这个问题不是一个特定的“可解决”问题,而是一个编程理论。 @Don 如果您非常担心对象的生命周期,这很重要。组合意味着当父对象被释放时,所有子对象都可以被释放,而聚合则相反;想想您的数据库代码从池中获取连接而不是在每次实例化数据库类时创建/销毁一个连接之间的区别。 【参考方案1】:

你关于房间和墙的问题的答案就是这个问题的答案:“没有房间,墙能存在吗?”

我相信您的方案正在使用聚合。没有房间,墙还能存在吗?当然可以。一个人可以通过摧毁三堵墙来摧毁房间,但剩下的那堵墙是独立的。我认为我们现在只剩下语义了。这个答案可能会根据你的场景中如何看待墙壁而改变。

这个link 展示了一种简洁的思考方式:

    A “拥有” B = Composition : B 在没有 A 的系统中没有意义或目的 A“使用”B = 聚合:B独立于A(概念上)存在

同样here:

聚合意味着子级可以独立于父级而存在的关系。示例:班级(父母)和学生(孩子)。删除班级,学生仍然存在。

Composition 意味着子级不能独立于父级而存在的关系。示例:房屋(父)和房间(子)。房间不是独立于房子而存在的

来自wikipedia:

聚合不同于普通的组合,它并不意味着所有权。在 composition 中,当拥有对象被销毁时,包含的对象也会被销毁。在聚合中,这不一定是正确的。例如,一所大学拥有多个系(例如化学),每个系都有许多教授。如果大学关闭,这些系将不复存在,但这些系的教授将继续存在。因此,大学可以看作是系的组合,而系则是教授的集合。此外,教授可以在多个系工作,但一个系不能隶属于多个大学。

【讨论】:

我想我知道你提到的概念,但是基于这个概念很难做出一个好的决定来建模这样一个问题,我认为这里有很多悖论,如果你破坏或删除整个对象(我的意思是房间)墙将不再存在,事实上它没有意义,所以从这个角度来看关系可能是组合,另一方面,在这个例子中我们可以看到有一个 Common在两个完整对象之间共享的部分部分的实例,据我所知,这在组合中是不允许的,那么选择哪个选项是正确的? @siamak 我相信您的场景正在使用聚合。没有房间,墙还能存在吗?当然可以。一个人可以通过摧毁三堵墙来摧毁房间,但剩下的那堵墙是独立的。我认为我们现在只剩下语义了。这个答案可能会根据你的场景中如何看待墙壁而改变。【参考方案2】:

Room 和 Wall 之间存在多对多关系。 (一墙可两房,一房可多墙。

我建议不要使用“CommonWall”之类的类,而是使用 Mapping 对象和两个 1-Many 关系来解决这个多对多问题。

public class Room 

public List<Wall> Wallsget;set;



public class Wall

decimal length;
decimal width;
public List<Room> Roomsget;set;


public class RoomWallMapping

public int MappingID;
public Wall get;set;
public Roomget;set;

【讨论】:

【参考方案3】:

Bob Horn 在这里提出了一个观点,当一堵墙可以独立于房间而存在时,它必须是一个聚合体。

但请记住,您模拟了您希望如何查看/操作它们,因此您还可以决定您主要关心您的房间并将墙壁视为房间的副作用,那么这就是一个组合。

聚合模型

你建造了墙,它定义了你的房间,你的房间就是墙之间的空间。

这样想,房间不需要有 4 面墙,它只是任意一组墙:开放式房间可以有 3 面墙,而 L 形封闭房间可能有 6 面。

这是建筑师或建筑商将采用的表示。

组成模型

您希望将房间视为有墙壁的空间,那么您真正关心的是从房间内侧看到的墙壁。在这种情况下,如果另一个房间有共同的墙壁,您就不会开车,当您破坏您的房间时,墙壁的内侧也会随之消失。

共享墙变成了两个房间墙的聚合。

如果您正在计划展览并希望确定绘画的放置位置,这可能是正确的表示。

模型最适合您的需求

最后,您对表示进行建模,从而进行简化。同样,在对表示进行建模时没有正确最佳答案,您应该根据需要对表示进行建模。

如果您想购买汽车,您倾向于将书定义为由其页面组成,当您处置它时,您会处置每一页。 如果您想打印一本书,您倾向于将您的零件作为由页面组成的聚合对开页进行备件,如果一个对开页打印错误,您可以从库存中取出另一页以组装成最终的书籍。

【讨论】:

【参考方案4】:

这取决于。一堵墙总是有两个面。 ;-)

在这种情况下,我会使用属性注入或构造函数注入,例如

public class Room

    public List<Wall> Walls  get; set; 
    public Room ( IEnumerable<Wall> walls )
    
        Walls = new List<Wall>(walls);
    

然后使用诸如builder pattern 之类的创建模式使用共享墙来构建房间。

【讨论】:

【参考方案5】:

如何处理房间和墙壁取决于手头的任务。

我将用两个例子来说明这一点,然后我会回过头来回答你问题的实际“要点”。

第一种方法(导航 1 层建筑):

目标:我想告诉机器人从当前位置移动到复制室。

我确定建筑物的尺寸,比如 100 英尺乘以 100 英尺。选择一个轴,然后制作一个点网格。机器人可以从位置 (50,50) 开始。接下来,我创建一个Graph,其中每条边代表从该节点到相应节点向北、东、南或西的一步。被墙隔开的节点具有无限的重量,即不能通过。

图形在邻接列表中表示。

现在我将 Room 定义为一个多边形并列出它的顶点。要测试机器人是否在房间内,它必须在房间多边形定义的区域内。在这种情况下,房间可能会重叠,尤其是因为在现实生活中站在门口可能意味着您在任何一个房间。

我的机器人现在可以在建筑物中导航、移动家具以及它想做的任何其他事情。

第二种方法:(面向对象)

建筑 属性 宽度、长度、高度、地理空间坐标、年龄等 外墙 可能是继承自 OuterWall 的 BrickWall、GlassWall、ConcreteWall 等 属性:位置、厚度等 方法:DemolishWall()、PaintExterior(Color C)等 内墙 可能是 NorthSouthWall 或 EastWestWall。 属性:hasDoorway、N/E 颜色、S/W 颜色等。 房间 属性:名称、位置、宽度、长度等

请注意,在这两个示例中,房间都没有直接引用它们的墙壁。

现在到您的问题的实际重点。如果两个对象具有共享资源,应该如何处理。

并行编程以各种不同的方式处理共享资源。

    为每个对象提供对共享资源的引用,确保同步或以其他方式处理共享资源上的并发行为。 将共享资源作为全局变量或通过单例对象、另一个类中的静态资源、甚至内存或文件系统中的特定位置提供给每个对象。 以预定义的顺序或在预定义的时间在并发部分之间传递共享资源。

想象一个酒店,每两个房间共用一个浴室:

HotelGuest A = new HotelGuest( new BusinessMan() );
HotelGuest B = new HotelGuest( new Programmer() );

A.Room = 101;
A.Bathroom = 7;
A.BathroomKey = getBathroomKey(7);

B.Room = 102;
B.Bathroom = 7;
B.BathroomKey = getBathroomKey(7);

//Asynchronously
A.RunDoBusinessStuff();
B.RunProgrammerStuff();

//but each has to lock bathroom7 when they use it, or it could be embarrassing.

但是在上面的例子中,卫生间怎么知道哪两个HotelGuest有它的钥匙呢?

    用当前客人和他们拥有的钥匙创建一个数据库,浴室可以查询数据库(或列表)。 在浴室属性中存储对 A 和 B 的引用。 (想象一下浴室里的白板列出了它的“租户”)。

【讨论】:

【参考方案6】:

如果这与真正的问题很接近,我想我不会想用普通的墙壁来组成房间。我更有可能收集 RoomComponents 或 IRoomComponents 将使用构造函数注入或属性注入注入。也有可能使用注入框架来组成房间,以便框架负责对象的生命周期。

如果我想象一下问题真的很简单,只有房间和墙壁,那么我猜你的方法 #4 看起来像是要走的路。我不确定什么是合适的名称,因为那里既有聚合又有组合。另一种方法是将公共墙设置为属性(如上所述的属性注入),而不是通过构造函数。

最后,如果我像这个线程中的其他人一样进入幻想世界,那么我很快就会意识到你所有的墙都应该是普通的墙!假设有人在现有房间的一堵墙周围建造了另外三堵墙-> bam 你有一个新的房间和一个新的公共墙。现在做什么?您可能想将现有墙更改为新的 CommonWall 对吧?所以在这种情况下,将墙作为属性似乎是不可避免的,否则每次你决定建造一个相邻的房间时,你都必须重新创建所有相邻的房间。

【讨论】:

以上是关于共同的墙壁和旁边的房间之间有啥样的关系?的主要内容,如果未能解决你的问题,请参考以下文章

举例简要说明啥是聚合关系,掌握聚合关系具有啥样的意义

mysql 分区的字段 与 where 的条件有啥样的关系啊

大数据在未来有啥样的发展趋势

表 Transaction 和 User - Ruby on Rails 应该使用啥样的关系?

WebGL和three.js的关系是啥样的?

SpringMVC的工作原理是啥样的,跟Spring的关系是怎么样的?