C#中组合和聚合的实现方式是什么?

8

如何在C#中实现组合和聚合?

谢谢, 123开发者

2个回答

20
那是一个相当抽象的问题,因为组合和聚合非常相似,只是在概念上有所不同,而不一定在代码层面上有所不同。(例如,你可能认为汽车拥有引擎是组合,而狗身上有跳蚤是聚合,但如果你在代码中对它们进行建模,没有什么能阻止你以相同的方式实现它们)。
然而,如果你想要分解差异并试图强制添加软件设计决策以突出这些差异,我想你可以做类似于这样的事情... 从维基百科中取一个例子
“聚合与普通组合的区别在于它不意味着所有权。在组合中,当拥有对象被销毁时,包含的对象也将被销毁。在聚合中,这并不一定是真的。例如,大学拥有各种部门(如化学),每个部门都有许多教授。如果大学关闭,部门将不再存在,但那些部门里的教授仍将继续存在。因此,大学可以被看作是由部门组成的,而部门则具有教授的聚合。此外,教授可以在多个部门工作,但一个部门不能成为多个大学的一部分。”
你可以构建这段代码来表示它(带有尽可能多的虚构的组合/聚合指示):
public class University : IDisposable
{
    private IList<Department> departments = new List<Department>();

    public void AddDepartment(string name)
    {
        //Since the university is in charge of the lifecycle of the
        //departments, it creates them (composition)
        departments.Add(new Department(this, name));
    }

    public void Dispose()
    {
        //destroy the university...
        //destroy the departments too... (composition)
        foreach (var department in departments)
        {
            department.Dispose();
        }
    }
}

public class Department : IDisposable
{
    //Department makes no sense if it isn't connected to exactly one
    //University (composition)
    private University uni;
    private string name;

    //list of Professors can be added to, meaning that one professor could
    //be a member of many departments (aggregation)
    public IList<Professor> Professors { get; set; }

    // internal constructor since a Department makes no sense on its own,
    //we should try to limit how it can be created (composition)
    internal Department(University uni, string name)
    {
        this.uni = uni;
        this.name = name;
    }

    public void Dispose()
    {
        //destroy the department, but let the Professors worry about
        //themselves (aggregation)
    }
}

public class Professor
{
}

3
虽然这是一个老问题,但我偶然发现了它。我的建议是,如果 Department 只是组成部分,您可以通过将其作为 University 的嵌套类并将其设置为私有来强制实施。这样就不可能在任何其他地方声明 Department,从而使父/子关系明确。 - Francisco Soto

5
在一个垃圾回收的世界中,所有对象都通过引用访问,在严格组合和聚合之间(在所有权方面)的微小差别变得有些模糊 - 因此通常情况下(使用类时),它可以归结为对于另一个对象或集合的字段:
class Building {
    private readonly List<Room> rooms = new List<Room>();
    public IList<Room> Rooms {get {return rooms;}}

    public Address Address {get;set;}
    //...
}
class Address {
    public string Line1 {get;set;}
    public string PostCode {get;set;}
    //...
}
class Room {
    public string Name {get;set;}
    public int Capacity {get;set;}
    //...
}

如果我理解有误,请澄清...
当讨论结构体时,事情变得更加复杂 - 但通常在讨论面向对象的概念时,结构体的使用仅限于值字段...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接