以编程方式区分组合和聚合

Differentiating Composition and Aggregation programmatically

我正在通过下面的内容 link 来弄清楚组合和聚合之间的区别。

https://www.geeksforgeeks.org/association-composition-aggregation-java/

我能够理解,组合意味着子不能独立于父存在的关系,而聚合意味着子可以独立于父存在的关系。但无法理解我如何以编程方式区分它。下面是 link.In 中给出的聚合和组合的示例,这两种情况 classes 在结构上是相同的,除了 Student 和 Department class 有一个额外的变量 "name" 。作为在 Composition "child cannot exist independent of the parent " 中,但在这里我可以创建一个单独的 Book 对象并在不将其添加到 Library 的情况下使用它。

聚合

// student class
class Student 
{
    String name;
    int id ;
    String dept;

    Student(String name, int id, String dept) 
    { 
        this.name = name;
        this.id = id;
        this.dept = dept;
    }
}



/* Department class contains list of student
Objects. It is associated with student
class through its Object(s). */
class Department 
{
    String name;
    private List<Student> students;

    Department(String name, List<Student> students) 
    {
        this.name = name;
        this.students = students;    
    }

    public List<Student> getStudents() 
    {
        return students;
    }
}

作文

class Book 
{
    public String title;
    public String author;

    Book(String title, String author)
    {
        this.title = title;
        this.author = author;
    }
}

// Libary class contains 
// list of books.
class Library 
{
    // reference to refer to list of books.
    private final List<Book> books;

    Library (List<Book> books)
    {
        this.books = books; 
    }

    public List<Book> getTotalBooksInLibrary()
    {
       return books;  
    }

}

在现实世界中,一本书 可以 确实存在,但不属于图书馆。但是,如果您有一个 LibraryBook class,其中包含 dateAcquiredcurrentBorrower 之类的字段怎么办?使用您的设计,您仍然可以在没有库的情况下创建 LibraryBook 实例。

这就是像 C++ 这样的语言可以更明确地说明组合的地方:在 C++ 中,一个对象可以按值 保存它的部分。在 Java 中,每个对象都由一个指针处理(好的,Java 人们不称它们为指针;而是称它们为引用。)这使得区分组合和聚合变得更加困难。在 Java 中,您使用精心设计来做到这一点。

例如,我们可以使 LibraryBook class 只能通过 Library:

的方法实例化
class Library {
    class LibraryBook {
        private LibraryBook() {/*private constructor prevents independent instantiation*/}
    }
    LibraryBook createBook(String title, etc...);
}

此外,如果我们让 LibraryBook 的修改器方法只能由图书馆 class 访问,我们可以确保这本书仍然是其所属图书馆的一部分。

据我所知(也许其他人可以给出更好的答案),您无法仅通过查看 Java 代码来评估这种关系是聚合还是组合。正好相反。

首先,您创建一个世界的概念模型。图书馆有书,汽车有轮子。然后你会想 - 在我工作的背景下 没有图书馆的书,或者没有汽车的轮子是否有意义,。因此,例如,如果您正在编写赛车游戏,您将无法在汽车之外使用轮子。但是如果你正在编写一些汽车修理应用程序,你将独立于某些特定汽车处理车轮。

所以首先你决定是否需要聚合或组合,然后在你的代码中实现它。实现可能是对象 CarList<Wheel> 但你无法判断它是组合还是聚合。关键是你根据你的概念模型来解释代码(实现),然后根据它来使用它。

如果是组合,使用上可能会有一些限制:

  • Car 外,没有任何对象会引用 Wheel
  • Wheel 甚至可能是私有的或包私有的 class.
  • 如果 Car 保存在数据库中,当您删除它时,您也会自动删除它的所有 Wheel

但是如果您决定它的组成,则由您来执行这些限制。