Composition and Aggregation in Object-Oriented Programming | 面向对象编程中的组合与聚合

📚 Composition and Aggregation in Object-Oriented Programming | 面向对象编程中的组合与聚合

In Edexcel A-Level Computer Science, mastering object-oriented relationships is crucial for designing maintainable and flexible software. This article explores two fundamental ‘has-a’ relationships — composition and aggregation — which define how objects work together to form complex systems. Understanding their differences and knowing when to apply each one will help you write better code and tackle exam questions with confidence.

在Edexcel A-Level计算机科学课程中,掌握面向对象的关系对于设计可维护、灵活的软件至关重要。本文探讨两种基本的“has-a”关系——组合与聚合,它们定义了对象如何协作构建复杂系统。理解它们的区别并知道何时应用哪一种,将帮助你写出更好的代码,并自信地应对考试题目。

1. What Is Object Association? | 什么是对象关联?

Objects rarely exist in isolation; they collaborate by forming relationships. An association describes a connection between two classes, allowing one object to send messages to another or use its functionality. In OOP, associations are typically divided into ‘is-a’ relationships (inheritance) and ‘has-a’ relationships (composition and aggregation). This article focuses on the latter two, which are essential for modelling real-world systems where a class contains or uses instances of other classes.

对象很少孤立存在;它们通过建立关系来协作。关联描述了两个类之间的连接,使得一个对象可以向另一个对象发送消息或使用其功能。在面向对象编程中,关联通常分为“is-a”关系(继承)和“has-a”关系(组合与聚合)。本文重点讨论后者,它们对于建模现实世界系统至关重要,在这些系统中,一个类包含或使用了其他类的实例。

For example, a Car class might have an Engine object — a ‘has-a’ relationship. Whether this relationship is composition or aggregation depends on the strength of the dependency. In exams, you’ll be expected to identify and justify these relationships based on lifecycle dependency and ownership.

例如,Car类可能有一个Engine对象——这是一种“has-a”关系。这种关系究竟是组合还是聚合,取决于依赖的强度。在考试中,你将被要求根据生命周期依赖性和所有权来识别并论证这些关系。


2. Defining Composition (Strong Association) | 定义组合(强关联)

Composition is a specialised form of association that represents a very strong relationship between two classes. When a class is composed of other classes, the composed objects cannot exist independently of the container. In other words, the lifetime of the component objects is managed by the composite object: they are created and destroyed together. This is often referred to as a ‘whole-part’ relationship with exclusive ownership.

组合是一种特殊的关联形式,表示两个类之间非常强的关系。当一个类由其他类组成时,被组合的对象不能独立于容器存在。换句话说,组件对象的生命周期由组合对象管理:它们一起创建,一起销毁。这通常被称为具有独占所有权的“整体-部分”关系。

Think of a House and a Room. A room belongs to exactly one house and cannot exist without it. If the house is demolished, its rooms are also destroyed. In programming terms, the House object would typically create Room instances in its constructor and delete them in its destructor (or use garbage collection). The contained object never exists outside the scope of its owner.

想想House与Room。一个房间只属于一栋房子,不能没有房子而独立存在。如果房子被拆除,它的房间也会被摧毁。在编程术语中,House对象通常会在其构造函数中创建Room实例,并在析构函数中删除它们(或使用垃圾回收)。被包含的对象永远不会在其所有者作用域之外存在。


3. Defining Aggregation (Weak Association) | 定义聚合(弱关联)

Aggregation is also a ‘whole-part’ relationship, but the link is weaker than composition. The part can exist independently of the whole and may be shared among different wholes. The container does not manage the lifecycle of the contained objects; they are typically passed in from outside. The relationship is best described as ‘uses-a’ rather than ‘owns-a’, because ownership is not exclusive.

聚合也是一种“整体-部分”关系,但关联比组合弱。部分可以独立于整体存在,并且可能被不同的整体共享。容器不管理被包含对象的生命周期;它们通常从外部传入。这种关系最好描述为“uses-a”而不是“owns-a”,因为所有权不是独占的。

A classic example is a Library and Books. Books can be removed from the library and added to another. They exist even if the library closes. In code, a Library object might receive Book objects through methods like addBook() and removeBook(), without creating or destroying them. The book’s lifetime is independent of the library.

一个经典的例子是Library与Book。书籍可以从图书馆移除并添加到另一家图书馆。即使图书馆关闭,书籍依然存在。在代码中,Library对象可能通过addBook()和removeBook()等方法接收Book对象,而不创建或销毁它们。书的生命周期独立于图书馆。


4. Key Differences Between Composition and Aggregation | 组合与聚合的关键区别

Exam questions often ask you to contrast composition and aggregation. The primary difference lies in lifecycle management and ownership. The table below summarises these differences to help you choose the appropriate relationship when modelling a problem.

考试题目经常要求比较组合与聚合。主要区别在于生命周期管理和所有权。下表总结了这些区别,以帮助你在建模问题时选择合适的关系。

Feature Composition Aggregation
Ownership Exclusive – part belongs to one whole Shared – part can belong to many wholes
Lifecycle Dependency Part cannot exist without whole Part can exist independently
Cascade Delete Yes – deleting whole deletes parts No – parts persist after whole is removed
Implementation Container creates and destroys parts Parts are passed in (injection)

5. UML Notation for Composition and Aggregation | 组合与聚合的UML表示法

In Unified Modelling Language (UML), both composition and aggregation are drawn as solid lines between classes, with a diamond at the whole end. The diamond is filled for composition (black diamond) and hollow for aggregation (white diamond). Being able to interpret these diagrams is a core skill for the Edexcel specification, as they frequently appear in design questions.

在统一建模语言(UML)中,组合和聚合都表示为类之间的实线,在整体端有一个菱形。组合使用实心菱形(黑色菱形),聚合使用空心菱形(白色菱形)。能够解读这些图表是Edexcel规范的核心技能,因为它们经常出现在设计类题目中。

For example, a filled diamond connecting University to Department would be incorrect if departments can exist before the university (they belong to an administrative body). Instead, a hollow diamond would represent a weaker dependency. Always consider whether the destruction of the whole necessarily destroys the part before choosing your diamond.

例如,如果用实心菱形连接University和Department,若系可以在大学之前存在(它们属于某个行政机构),那就是不正确的。相反,空心菱形将代表较弱的依赖关系。在选择菱形之前,始终要考虑整体的销毁是否一定会销毁部分。


6. Implementing Composition in Code (Python) | 用代码实现组合 (Python)

Let’s see how composition is coded in Python, a language commonly used in the Edexcel course. In composition, the whole object is responsible for instantiating its parts and holding strong references. The part objects are typically stored as private attributes and are not exposed to external creation.

我们来看看如何在Python中编写组合代码,这是Edexcel课程中常用的语言。在组合中,整体对象负责实例化其部分并持有强引用。部分对象通常存储为私有属性,并且不暴露给外部创建。

class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower
    def start(self):
        return "Engine started"

class Car:
    def __init__(self, model, hp):
        self.model = model
        # Composition: Car creates and owns Engine
        self.__engine = Engine(hp)

    def drive(self):
        return f"{self.model} driving with {self.__engine.horsepower} HP"

my_car = Car("Tesla", 400)
# The engine cannot be accessed directly or exist without the car
del my_car  # Both car and its engine are gone

In this example, the Engine object is created inside the Car constructor, and no external reference to it exists. When the Car instance is deleted, the engine is no longer reachable, so it will be garbage collected. This pattern satisfies the composition test — the part’s lifetime is fully tied to the whole.

在这个例子中,Engine对象在Car的构造函数中创建,且不存在对它的外部引用。当Car实例被删除时,引擎不再可达,因此将被垃圾回收。这种模式满足组合测试——部分的生命周期完全与整体捆绑。


7. Implementing Aggregation in Code (Python) | 用代码实现聚合 (Python)

Aggregation is implemented by accepting external objects as parameters (often through a constructor or setter). The whole class does not create or destroy the part; it simply stores a reference to it. The part may be shared among several containers simultaneously.

聚合的实现方式是将外部对象作为参数接受(通常通过构造函数或setter)。整体类不创建也不销毁部分;它只是存储对它的引用。部分可能同时被多个容器共享。

class Book:
    def __init__(self, title):
        self.title = title

class Library:
    def __init__(self, name):
        self.name = name
        self.books = []  # Aggregation: Library uses but does not own books

    def add_book(self, book):
        self.books.append(book)

    def remove_book(self, book):
        self.books.remove(book)

b1 = Book("1984")
b2 = Book("Brave New World")
lib = Library("City Central")
lib.add_book(b1)
lib.add_book(b2)
# Books still exist if library is deleted
del lib  # b1 and b2 remain

Notice that the Book objects exist before being added to the library, and they survive after the library object is removed. This illustrates the loose coupling characteristic of aggregation, making it suitable for scenarios where objects must persist beyond their containers.

注意,Book对象在添加到图书馆之前就已经存在,并且在图书馆对象被移除后仍然存在。这体现了聚合松耦合的特性,使其适用于对象必须在其容器之外持久存在的场景。


8. Choosing Between Composition and Aggregation | 在组合与聚合之间做出选择

Choosing the right relationship starts with analysing the real-world problem domain. If the part is meaningless outside the context of the whole and must never be shared, composition is appropriate. This simplifies memory management and ensures data integrity, as the part cannot be altered by other objects unexpectedly.

选择正确的关系始于分析现实世界的问题域。如果部分脱离整体语境就毫无意义,且绝不能被共享,那么组合是合适的。这简化了内存管理并确保了数据完整性,因为部分不会被其他对象意外更改。

On the other hand, if the part has its own identity and may collaborate with other wholes, aggregation offers greater flexibility. It promotes reuse and reduces tight coupling, which is a fundamental design principle. Always ask: ‘Does the part logically belong to exactly one whole?’ If yes, composition; if it can be shared or stand alone, aggregation.

另一方面,如果部分有自己的身份并且可能与其他整体协作,聚合则提供了更大的灵活性。它促进了重用并减少了紧耦合,这是一条基本设计原则。始终要问:“部分在逻辑上是否只属于一个整体?”如果是,则用组合;如果它可以被共享或独立存在,则用聚合。


9. Composition vs Inheritance: A Critical Comparison | 组合与继承:重要对比

Another common exam theme is comparing ‘has-a’ (composition) with ‘is-a’ (inheritance). Composition allows you to assemble complex behaviour by combining discrete objects, while inheritance lets you derive a new class from an existing one. The principle ‘favour composition over inheritance’ is often stressed because composition leads to more flexible, loosely coupled designs.

另一个常见的考试主题是“has-a”(组合)与“is-a”(继承)的对比。组合允许你通过组合离散对象来组装复杂行为,而继承让你从现有类派生出新类。通常强调“优先使用组合而非继承”的原则,因为组合能产生更灵活、松耦合的设计。

For instance, if you want a Stack data structure, you could inherit from a List, but this exposes all list methods to the stack, breaking encapsulation. A better design is to use composition: the Stack class contains a private list and only exposes push(), pop(), and peek(). This hides implementation details and prevents misuse.

例如,如果你想要一个Stack数据结构,你可以从List继承,但这会将所有列表方法暴露给栈,破坏了封装性。更好的设计是使用组合:Stack类包含一个私有列表,并仅暴露push()、pop()和peek()方法。这就隐藏了实现细节并防止了误用。

The Edexcel exam may ask you to evaluate the suitability of inheritance versus composition for a given scenario. Be prepared to justify your choice with clear arguments about flexibility, code maintainability, and the nature of the relationship between entities.

Edexcel考试可能会要求你评估继承与组合在给定场景中的适用性。准备好用关于灵活性、代码可维护性以及实体之间关系性质的清晰论据来证明你的选择。


10. Common Mistakes and How to Avoid Them | 常见错误及如何避免

Students often confuse composition with aggregation when the terms are used loosely. Remember that if the part can be accessed or manipulated outside the containing class without breaking the model, it’s likely aggregation. Another mistake is using composition when objects need to be shared across multiple containers, which leads to unintended duplication and inconsistent state.

当术语被宽松使用时,学生经常混淆组合与聚合。请记住,如果部分可以在不破坏模型的情况下在包含类外部被访问或操作,那很可能是聚合。另一个错误是在对象需要在多个容器之间共享时使用组合,这会导致意外的重复和不一致的状态。

In code, avoid exposing internal composed objects through public getters, as this breaks encapsulation and weakens the composition guarantee. Instead, provide controlled methods that respect the lifecycle. Also, never make a composed object a global variable — it defeats the purpose of strong ownership.

在代码中,避免通过公共getter暴露内部组合的对象,因为这会破坏封装并弱化组合保证。取而代之,提供尊重生命周期的受控方法。此外,绝不要让组合对象成为全局变量——这会违背强所有权的目的。


11. Practice Scenario: University System | 实践场景:大学系统

Consider modelling a university system. A University has Departments, and each Department has Lecturers. Apply what you’ve learned: is the relationship between University and Department composition or aggregation? If the university is closed, do departments cease to exist? Typically, departments belong to a larger academic structure and may be reassigned, so aggregation is appropriate.

考虑给大学系统建模。一所大学有院系(Department),每个院系有讲师(Lecturer)。应用你所学:大学与院系之间是组合还是聚合关系?如果大学关闭,院系会消失吗?通常,院系属于更大的学术结构,可能被重新分配,因此聚合是合适的。

What about Department and Lecturer? A lecturer might work for multiple departments or leave the university while the department persists. Hence, that relationship is also aggregation. Inside a Department, it might own a Lab — if the department is dissolved, the lab is dismantled. This is a candidate for composition. Analysing such scenarios sharpens your design skills for the exam.

那么院系与讲师呢?一位讲师可能服务于多个院系,或离开大学而院系仍存在。因此,这个关系也是聚合。在院系内部,它可能拥有实验室——如果院系解散,实验室也会被拆除。这就是组合的候选。分析这些场景可以提升你在考试中的设计技能。


12. Exam Tips for Composition and Aggregation | 组合与聚合的考试技巧

When answering Edexcel questions, clearly define the relationship you’re proposing and justify it with lifecycle arguments. Use UML notation correctly — filled diamond for composition, open diamond for aggregation. If asked to write code, demonstrate proper construction and destruction logic. Show that you understand the impact on data integrity and memory management.

在回答Edexcel题目时,清晰地定义你提议的关系,并用生命周期论证来证明。正确使用UML符号——组合用实心菱形,聚合用空心菱形。如果要求编写代码,展示适当的构造和销毁逻辑。表明你理解这对数据完整性和内存管理的影响。

For the longer design questions, compare the trade-offs explicitly: composition provides strong consistency and simpler cleanup, while aggregation offers greater reusability. Remember that neither is universally better — they solve different problems. Practise with past paper scenarios to become fluent in identifying ‘has-a’ relationships and categorising them correctly.

对于较长的设计题,明确比较权衡:组合提供强一致性和更简单的清理,而聚合提供了更大的可重用性。请记住,两者都不是普遍更好的——它们解决不同的问题。用历年真题的场景进行练习,以熟练地识别“has-a”关系并正确归类。

Published by TutorHao | Programming Revision Series | aleveler.com

更多咨询请联系16621398022(同微信)

Comments

屏轩国际教育cambridge primary/secondary checkpoint, cat4, ukiset,ukcat,igcse,alevel,PAT,STEP,MAT, ibdp,ap,ssat,sat,sat2课程辅导,国外大学本科硕士研究生博士课程论文辅导Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from aleveler.com

Subscribe now to keep reading and get access to the full archive.

Continue reading

Exit mobile version