类关系:关联与组合
在面向对象编程中,类之间相互作用以实现应用程序的一个或多个功能。您可以在设计应用程序的类时定义类之间的关系。
根据一个类与另一个类交互的方式,面向对象编程中有三种类型的关系。
- 关联
- 组合
- 组合
- 聚合
- 继承
下图说明了这些关系。

关联
关联关系被称为“使用”关系,其中一个类使用另一个类来执行某些操作。在关联中,两个类都可以独立存在,彼此不拥有对方。有些人将关联称为协作或委托。
关联发生在类之间,其中一个类为另一个类提供服务,或者一个类将某种行为委托给另一个类。
关联通常通过指针或引用实例变量或作为方法参数来实现。
以下示例演示了 `Student` 和 `StudentRepository` 类之间的关联关系。
public class Student
{
public int StudentId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
public class StudentRepository
{
public Student GetStudent(int StudentId)
{
// get student by id from db here
return new Student();
}
public bool Save(Student student)
{
// save student to db here
Console.WriteLine("Student saved successfully");
return true;
}
public bool Validate(Student student)
{
// get student from db to check whether the data is already exist
Console.WriteLine("Student does not exist.");
return true;
}
}
在上面的示例中,`StudentRepository` 类使用 `Student` 类来保存或检索学生数据。请注意,`StudentRepository` 类将 `Student` 类作为方法的参数使用。`StudentRepository` 类为任何对保存或检索学生数据感兴趣的类提供服务。然而,这两个类具有独立的生命周期,这意味着处理一个类并不会处理另一个类。因此,我们可以说 `StudentRepository` 类和 `Student` 类之间的关系是关联(或协作/委托)。您也可以说 `Student` 类将保存和检索学生相关数据的实现责任委托给了 `StudentRepository` 类。
类之间的关联关系在 UML 图中用箭头标记,如下图所示。

重要事项
- 一个类只使用另一个类的行为/功能(方法),但不会通过覆盖它们来改变它们。
- 一个类不继承另一个类。
- 一个类不将另一个类作为公共成员包含(拥有)。
- 两个类都具有独立的生命周期,处理一个类不会自动处理另一个类。
组合
组合被称为“拥有”关系。当一个类将另一个类作为实例属性引用时,就形成了组合关系。
在组合关系中,包含另一个类引用的类是该子类的父类(所有者)。没有父类的子类不存在。
@*组合关系分为两类
- 组合
- 聚合

例如,下面的 `Student` 类与保存学生地址的 `Address` 类具有复合关系。没有 `Student` 对象的 `Address` 对象无法存在。
public class Student
{
public int StudentId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public Address HomeAddress { get; set; }
}
public class Address
{
public int AddressId { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string Country { get; set; }
}
在上面的例子中,`Student` 类将 `Address` 类作为公共属性,这使得 `Student` 和 `Address` 类之间存在复合关系。如果 `Student` 对象被删除,那么 `Address` 对象也将被删除。
复合关系还具有基数,即类之间的一对一、一对多或多对多关系。在上面的示例中,`Student` 和 `Address` 类具有一对一关系,因为每个 `Student` 将只有一个地址。
一个类也可以包含另一个类的 `id` 属性而不是实例来形成复合关系。例如,`Student` 类可以包含指向 `Address` 类的 `AddressId` 属性。
public class Student
{
public int StudentId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public int AddressId { get; set; }
}
类之间的组合关系在 UML 图中用线标记,如下图所示。

重要事项
- 一个类(父类)包含对另一个类(子类)的引用。
- 没有父类,子类就不存在。
- 删除父类也会删除子类
- 一个类也可以包含另一个类的id属性的引用。
聚合
聚合是“拥有”关系的另一类,其中一个类可以包含其他类作为属性,但这些类可以独立存在。
例如,`Student` 类包含 `Course` 类实例作为属性以形成组合关系。然而,这两个类都可以独立存在,因此它被称为聚合关系。
public class Student
{
public int StudentId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public Course EnrolledCourse { get; set; }
}
public class Course
{
public int CourseId { get; set; }
public string CourseName { get; set; }
public IList<string> Topics { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
在上述聚合关系中,即使 `Student` 对象被删除,`Course` 对象仍然存在。`Student` 类也可以包含 `CourseId` 属性而不是 `Course` 实例。
组合和聚合都是“拥有”关系,但在组合关系中,相关类不能独立存在,而在聚合关系中,相关类可以独立存在。
类之间的聚合关系在 UML 图中用线标记,如下图所示。

重要事项
- 聚合是另一种组合类型(“拥有”关系)。
- 一个类(父类)包含对另一个类(子类)的引用,其中两个类都可以独立存在。
- 一个类也可以包含另一个类的id属性的引用。