Java最高

开始使用Spring 5和Spring Boot 2,通过学习的春天课程:

>>查看课程

1.介绍

对象之间有关系,无论是在现实生活中还是在编程中。有时很难理解或实现这些关系。

在本教程中,我们将重点介绍Java采用的三种有时容易混淆的关系类型:组合、聚合和关联。

2.组成

作品是一个“属于”的关系类型。这意味着其中一个对象是逻辑上更大的结构,其包含另一个对象。换句话说,它是另一个对象的部分或成员。

另外,我们通常称其为“有-有”关系(而不是“是一个”的关系,这是遗产)。

例如,一个房间属于建筑物,或者换句话说,建筑物有一个房间。所以基本上,我们是否称之为“属于”或“有”只是一个观点的问题。

构成是一种强烈的“有一个”的关系,因为包含的对象拥有它。所以,对象的生命周期被捆绑在一起。这意味着如果我们销毁所有者对象,其成员也将被摧毁。例如,房间在前面的示例中与建筑物销毁。

请注意,这并不意味着包含对象没有它的任何部分就不能存在。例如,我们可以拆除建筑物内的所有墙壁,从而摧毁房间。但这座建筑仍将存在。

就基数而言,一个包含的物体可以拥有我们想要的多样性。然而,所有部件都需要完全一体的容器

2.1。UML

在UML中,我们用下面的符号来表示组合:

注意,钻石位于包含对象,是线的基础,而不是箭头。为了清楚起见,我们经常也绘制箭头:

那么,我们可以在buildroom示例中使用这个UML构造:

2.2。源代码

在Java中,我们可以用一个非静态内部类来建模:

教室{}}

或者,我们也可以在方法体中声明该类。它是一个命名类、一个匿名类还是一个lambda并不重要:

class Building {Room createAnonymousRoom() {return new Room() {@Override void doInRoom() {}};}房间createInlineRoom(){类InlineRoom实现房间{@Override void doInRoom(){}}返回新的InlineRoom();}房间createLambdaRoom() {return () -> {};}接口房间{void doInRoom();}}

注意,内部类必须是非静态的,因为它将所有实例绑定到包含类。

通常,包含对象想要访问其成员。因此,我们应该存储他们的参考资料:

Class Building {list  room;班级室{}}

注意,所有内部类对象都存储了对其包含对象的隐式引用。因此,我们不需要手动存储它来访问它:

class Building {String address;class Room {String getBuildingAddress() {return Building.this.address;}}}

3.聚合

聚合也是一种“has-a”关系。它与构成的区别在于,它不涉及拥有。因此,对象的生命周期并不是绑定的:它们中的每一个都可以彼此独立地存在。

例如,一辆汽车和它的轮子。我们可以脱掉车轮,他们仍然存在。我们可以安装其他(已存在的)车轮,或将这些安装到另一辆车上,一切都会很好。

当然,没有轮子或拆卸轮的汽车不会像轮子一样有用。但这就是为什么这一关系首先存在:把这些部件组装成一个更大的结构,这个结构比它的部件能做更多的事情

由于聚集不涉及拥有,成员不需要只绑定到一个容器。例如,三角形是由段制成的。但三角形可以将细分分享到他们的方面。

3.1。UML

聚合与组合非常相似。唯一的逻辑区别是聚合是一个较弱的关系。

因此,UML表示也非常相似。唯一的区别是钻石是空的

对于汽车和轮子,我们会:

3.2。源代码

在Java中,我们可以用一个简单的旧引用来建模聚合:

class Wheel {} class Car {List<车轮>车轮;}

除非非静态内部类,成员可以是任何类型的类。

在两个类上方的代码片段中,都有其单独的源文件。但是,我们也可以使用静态内部类:

class Car {List<车轮>车轮;静态类Wheel {}}

请注意,Java将仅在非静态内部类中创建隐式引用。因此,我们必须手动维护我们需要的关系:

类车轮{车车;} class Car {List<车轮>车轮;}

4.协会

协会是三个之间最薄弱的关系。这不是一个“有一个”的关系,没有一个对象是另一个对象的部分或成员。

协会仅意味着对象“彼此知道”。例如,一位母亲和她的孩子。

4.1。UML

在UML中,我们可以标记与箭头的关联:

如果关联是双向的,我们可以使用两个箭头,一个两端都有箭头的箭头,或者一条没有箭头的线:

我们可以代表一个母亲和她的孩子,然后:

4.2。源代码

在Java中,我们可以将关联与聚合相同的方式:

Class Child {}类母亲{list 儿童;}

可是等等,我们如何判断参考是否意味着聚合或关联?

嗯,我们不能。区别只是逻辑上的:一个对象是否是另一个对象的一部分。

此外,我们必须在两端手动维护引用,因为我们使用聚合时:

班童母亲{母亲妈妈;}类母亲{list 儿童;}

5.UML旁注

为了清晰起见,有时我们想在UML图上定义关系的基数。我们可以把它写在箭头的末尾:

注意,把0写成基数是没有意义的,因为这意味着没有关系。唯一的例外是当我们想要使用range来指示一个可选关系时:

还要注意,因为在组合中只有一个所有者,所以我们没有在图中指出它。

6.一个复杂的例子

让我们来看一个更复杂的例子!

我们将建模大学,其中有其部门。教授在每个部门工作,谁也有相互的朋友。

我们关闭学校后,这些系还会存在吗?当然不是,因此它是一个合成。

但教授仍然存在(希望)。我们必须决定哪个更合乎逻辑:如果我们认为教授作为部门的一部分。或者:他们是部门的成员吗?是的,他们是。因此它是一个聚合。最重要的是,教授可以在多个部门工作。

教授之间的关系是一种联系,因为说一个教授是另一个教授的一部分是没有任何意义的。

结果,我们可以使用以下UML图来模拟此示例:

java代码如下所示:

class University {List Department;} class Department {List professors;} class教授{List Department;<列表>教授朋友;}

注意,如果我们依赖“has-a”,“belong -to”,“member-of”,“part-of”等等,我们可以更容易地识别对象之间的关系。

7.结论

在本文中,我们看到了组成,聚合和协会的属性和代表性。我们还显示如何在UML和Java中模拟这些关系。

像往常一样,有一些例子在github上

Java底部

开始使用Spring 5和Spring Boot 2,通过学习的春天课程:

>>查看课程
评论在本文上关闭!