我想知道共同墙(位于相邻房间)与房间之间的关系。
我知道房间和墙壁之间的关系是Composition not Aggregation
(我是对的吗?)
And according to the definition of
撰写 the contained object can't be shared between two
containers, whereas in
聚合 it is possible
。
现在我很困惑,最好的建模方法是什么来表示公共墙和旁边房间之间的关系?
如果你能为你的建议提供一些代码,那将是非常赞赏的。
| -------- | -------- |
Approch1:
(wall class ---- room class) /Composition
Approach2:
wall class ----- room class /Aggregation
Approch3:
我们有一个wall类和一个Common wall类,Common wall类继承自wall类
adjoining room class ---- (1) Common wall class /Aggregation
adjoining room class ---- (6) wall class / composition
Approach4: 我是开发人员而非设计师:)所以这是我的想法:
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个墙和一扇门的封闭的方形房间。但在这种情况下,这些墙中的一个是共同的墙,在两个相邻的墙之间共用室。
答案 0 :(得分:16)
关于房间和墙壁的问题的答案就是这个问题的答案:“没有房间,墙可以存在吗?”
我相信您的方案正在使用聚合。没有房间的墙可以存在吗?当然可以。人们可以通过摧毁三面墙来破坏房间,但剩下的墙壁就是独立的。我认为我们现在已经归结为语义。此答案可能会根据您在 场景中查看墙壁的方式而有所变化。
这个link显示了一种简洁的方式来思考它:
相同here:
聚合表示子项可以独立于父项存在的关系。示例:Class(父级)和Student(子级)。删除班级,学生仍然存在。
组合意味着孩子不能独立于父母而存在的关系。示例:住宅(父母)和房间(儿童)。房间不是独立于房子
来自wikipedia:
汇总与普通组合的不同之处在于它并不意味着所有权。在组合中,当拥有对象被销毁时,包含的对象也是如此。在聚合中,这不一定是真的。例如,一所大学拥有各个部门(例如化学),每个部门都有一些教授。如果大学关闭,部门将不复存在,但这些部门的教授将继续存在。因此,大学可以被视为一个部门的组合,而部门则有教授的集合。此外,教授可以在多个部门工作,但一个部门不能成为一所以上大学的一部分。
答案 1 :(得分:2)
Room和Wall之间有很多关系。 (一个墙可以在两个房间使用,一个房间可以有多个墙。
我建议不要使用像“CommonWall”这样的类,而是使用Mapping对象和两个1-Many关系来解决这个问题。
public class Room
{
public List<Wall> Walls{get;set;}
}
public class Wall
{
decimal length;
decimal width;
public List<Room> Rooms{get;set;}
}
public class RoomWallMapping
{
public int MappingID;
public Wall {get;set;}
public Room{get;set;}
}
答案 2 :(得分:2)
Bob Horn 在这里提出了一个观点,当一个墙可以独立于房间而存在时,它必须是一个聚合。
但请记住,你要模拟你想要如何看待/操纵它们,所以你也可以决定你主要关心你的房间并看到墙壁作为房间的副作用,然后这是一个组合。
汇总模型
你建造了墙壁并且定义了你的房间,你的房间就是墙壁之间的空间。
这样想,房间不需要有4面墙,它只是一组任意墙:一个开放的房间可以有3面墙,一个L形的封闭房间可能有6面。
这是建筑师或建筑商将采用的表示。
作文模型
你想看到一个房间是一个有墙的空间,那么你真正关心的是从房间内侧看到的墙。在这种情况下,如果另一个房间有一个共同的墙,你不会开车,当你摧毁你的房间时,墙的内侧会随之消失。
共享墙成为两个房间墙的集合。
如果您正在筹划展览并希望定义将放置绘画的位置,这可能是正确的表示。
建模最符合您需求的
最后,您可以对表示进行建模,从而简化。同样,在对表示进行建模时,没有正确的或最佳答案,您应该根据需要对表示进行建模。
如果您想购买汽车,您倾向于将书籍定义为由其页面组成,当您处理它时,您将处理每一页。 如果你想要打印一本书,你倾向于将你作为聚合由页面组成的作品集来备件,如果作品集被错误打印,你可以从库存中取出另一本书来组装成最终书。
答案 3 :(得分:1)
这取决于。墙上总是有两面。 ; - )
在这种情况下,我会使用属性注入或构造函数注入,例如
public class Room
{
public List<Wall> Walls { get; set; }
public Room ( IEnumerable<Wall> walls )
{
Walls = new List<Wall>(walls);
}
}
然后使用创建模式(如builder pattern)使用共享墙构建房间。
答案 4 :(得分:1)
你如何应对Rooms and Walls取决于手头的任务。
我将用两个例子来说明这一点,然后我会回过头来回答你问题的实际“要点”。
第一种方法(导航1层楼):
目标:我想告诉机器人从当前位置移动到复制室。
我确定建筑物的尺寸,比如100英尺,100英尺。选择一个轴,并制作一个点网格。机器人可以从位置(50,50)开始。接下来,我创建一个Graph,其中每条边表示从该节点到相应节点的北,东,南或西的一步。由墙隔开的节点具有无限重量,即不能通过。
图表以邻接列表表示。
现在我将Room定义为多边形并列出其顶点。要测试机器人是否在房间内,它必须位于房间多边形定义的区域内。在这种情况下,房间可以重叠,特别是因为在现实生活中站在门口可能意味着你在任何一个房间。
我的机器人现在可以在建筑物中移动,移动家具,以及其他任何想要做的事情。
第二种方法:(面向对象)
请注意,在这些示例中,房间都没有直接引用它们的墙壁。
现在问题的实际意义。如果两个对象具有共享资源,应该如何处理。
并行编程以各种不同的方式处理共享资源。
想象一下,每两个房间之间有一个共用浴室的酒店:
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.
但在上面的例子中,卫生间如何知道哪两个酒店顾客有钥匙?
答案 5 :(得分:1)
如果这是真正的问题,我不认为我想要从普通的墙壁组成房间。我更有可能收集使用构造函数注入或属性注入注入的RoomComponents或IRoomComponents。还可以使用注入框架来组成Room,以便框架处理对象的生命周期。
如果有一秒钟,我会想到问题真的很简单,只有Room和Walls,那么我想你的方法#4看起来就像是要走的路。我不确定那是什么名称,因为你有聚合和组合。另一种方法是将公共墙设置为属性(如上所述的属性注入),而不是通过构造函数。
最后,如果我像其他人一样进入幻想世界,那么我很快就会意识到你所有的墙应该是共同的墙!假设某人在现有房间的一面墙周围建造了另外三面墙 - &gt;因为你有一个新的房间和一个新的共同墙。现在做什么?您可能希望将现有墙更改为新的CommonWall吗?因此,在这种情况下,似乎不可避免地将墙作为属性,否则每次您决定构建邻居房间时,您都必须重新创建所有相邻房间。