实例化创建一个对象实例(许多语言为此使用new 关键字),而聚合描述对象之间的关系(已经创建或实例化)。
为避免混淆,我必须指出,此示例中使用的所有术语(如 aggregation)均在 Martin Fowler 的上下文中使用,他引入了与 UML 标准定义不同的定义或措辞。
从您的图表中:
聚合
给出了两个类定义Drawing 和Shape,根据您提供的图表,它们具有称为聚合 的关系,根据定义描述了一个共享 em> 这两个对象的生命周期。这意味着Drawing“包含”任意数量的Shapes,或者更准确地说,Shape 是Drawing 的一部分。当所有者 (Drawing) 的生命周期结束时,Shape 的生命周期也将结束:
// The `Shape` class
class Shape
{
...
}
// The `Drawing`class that aggregates a single `Shape`
class Drawing
{
// The reference to the instance of `Shape`
private Shape shape;
// The constructor
public Drawing()
{
// Create an instance of `Shape`.
// Because the relationship between `Drawing`and `Shape`is an aggregation the instantiation occurs inside the owners constructor (opposed to outside the owner object).
this.shape = new Shape();
}
}
因为Drawing和Shape之间的关系是一个聚合,所以Shape类型的实例化发生在内部所有者构造函数(在熟人的情况下与所有者对象之外的对象相反)。
认识
图中描绘的另一种关系是熟人。 熟人存在于LineShape 和Color 类型的对象之间。这意味着LineShape 使用 Color。 Color 将独立于其拥有的 LineShape 对象。对象CreationTool 和LineShape 之间的虚线描述了一个实例化(创建)。这意味着CreationTool 创建了LineShape 的实例。这是必需的,因为与 aggregation 相反,acquaintance 描述了两个对象的独立生命周期。 Color 可以在其他 Shape 对象之间共享。这需要 LineShape 的相关对象,Color 对象,在所有者之外(而不是在所有者的构造函数内部,如 聚合 场景):
// The `LineShape` class
class Color
{
...
}
// The `LineShape`class that acquaints or associates with a single `Color`
class LineShape
{
// The reference to the instance of `Shape`
private Color color;
// The constructor
public LineShape(Color sharedColorInstance)
{
// Request an instance of `Shape` as constuctor parameter.
// Because the relationship between `LineShape`and `Color`is an acquaintance the instantiation occurs outside the owners constructor (opposed to inside the owner object).
this.color = sharedColorInstance;
}
}
// The `CreationTool` class that creates an instance of `LineShape
// and passes a shared instance of `Color`into the constructor.
class CreationTool
{
Color color = new Color();
// Create the instance of `LineShape`
// to satisfy the dashed line (relationship) in the diagramm
LineShape firstLine = new LineShape(color);
// To show the benefit of acquaintance a second instance of `LineShape` is created
// using the same `Color` instance
LineShape secondLine = new LineShape(color);
// When firstLine's lifetime ends,
// secondLine still has a valid instance of `Color`
}
因为LineShape和Color之间的关系是熟人,所以实例化发生在外部所有者构造函数(相对于内部聚合场景中的所有者对象)。这样,Color 的单个实例就可以在多个所有者之间共享。
正如您在代码示例中看到的,两个关系(或一般的关系)要求将指向相关对象的引用存储在所属对象中。唯一的区别是查看所拥有对象的创建位置哪里。这种情况将描述关系的特殊形式:相关对象是在所有者外部实例化的(熟人)还是在所有者内部实例化的(聚合)?
这意味着您可以通过查看构造函数(或实例化)来区分这两种类型的关系:是传递给构造函数的相关对象实例还是所有者的 setter 方法(熟人)还是所有者的构造函数无参数或无设置器(聚合)?
对于实例化,字段的要求是另一回事。我们可以说,当CreationTool 实例化LineShape 时,它不需要一个字段来存储对该对象的引用。但是在Color 的情况下,CreationToolobject 可以在字段中存储对Color 实例的引用,以便在创建新的LineShape 实例时重用它(共享它),因为Color 的实例是需要满足LineShape的构造函数。因此,如果需要一个字段来存储对创建者内部已创建实例的引用,这首先是完全可选的,并且取决于上下文。
此时应该提到,如果是熟人,另一种“注入”拥有的对象实例的方法是使用setter方法:
Color color = new Color();
LineShape shape = new LineShape();
shape.SetColor(color);
尽可能使用构造函数。
另一个说明,只是为了使它更完整:当用于实现这种关系的语言具有自动内存管理(垃圾收集)时,生命周期控制方面就不再相关了。在 M. Fowlers 世界(或在 UML 世界中的 聚合)中,一切都变成了熟人,因为只要有任何引用存储到拥有的对象实例(例如,当暴露实例通过 getter 方法),垃圾收集器不会破坏此实例,它将继续存在 - 独立于所有者。