当对象A实例化/聚集/认识对象B时,对象A是否必须具有引用对象B的字段成员?
来自GoF的设计模式:
From Design Pattern by GoF:
代表部分关系或聚集关系的对象引用是
,由底部有钻石的箭头线。箭头指向
已被聚合的类(例如Shape)。没有菱形
的箭头线表示相识(例如,LineShape保留对Color对象的引用,其他
形状可能会共享该对象)。引用的名称可能会出现在底部附近,以将
与其他引用
区别开来。还有一个有用的事情是显示哪些实例 instantiate
哪个类。我们使用虚线箭头来表示这一点,因为OMT不支持
。我们称此为创建
关系。箭头指向实例化的类。在
图B.lc中,CreationTool创建了LineShape对象。
An object reference representing a part-of or aggregation relationship is indicated by an arrowheaded line with a diamond at the base. The arrow points to the class that is aggregated (e.g., Shape). An arrowheaded line without the diamond denotes acquaintance (e.g., a LineShape keeps a reference to a Color object, which other shapes may share). A name for the reference may appear near the base to distinguish it from other references Another useful thing to show is which classes instantiate which others. We use a dashed arrowheaded line to indicate this, since OMT doesn't support it. We call this the "creates" relationship. The arrow points to the class that's instantiated. In Figure B.lc, CreationTool creates LineShape objects.
-
当对象A聚合对象B时,对象A是否必须具有引用对象B的字段成员?
-
when object A aggregates object B, must object A have a field member referencing object B?
当对象A认识对象B时,对象A是否必须具有引用对象B的字段成员?
when object A acquaints object B, must object A have a field member referencing object B?
当对象A时实例化对象B,对象A是否必须具有引用对象B的字段成员?
when object A instantiates object B, must object A have a field member referencing object B?
-
实例化创建一个对象实例(许多语言为此使用 new
关键字),而聚合则描述了对象(已经创建或实例化)之间的关系。
为防止混淆,我必须指出,本示例中使用的所有术语(例如 aggregation )都是在Martin Fowler的上下文中使用的,与FML相比,Martin Fowler引入了不同的定义或措辞
Instantiation creates an object instance (many languages are using the new
keyword for this) while aggregation describes the relationship between objects (that are already created or instantiated).
To prevent confusion I have to point out that all terms used in this example like aggregation are used in the context of Martin Fowler, who has introduced a different definition or phrasing in contrast to the UML standard definition.
从图中:
根据提供的图表,有两个类定义 Drawing
和 Shape
称为 aggregation (聚合),根据定义,它描述了这两个对象的共享生存期。这意味着绘图
由任意数量的形状
组成,或更准确地说,是形状
是工程图
的一部分。当所有者的生命周期(绘图
)结束时, Shape
的生命周期也将结束:
given are the two class definitions Drawing
and Shape
that have, according to your provided diagram, a relationship which is called aggregation, which by definition describes a shared lifetime of those two objects. This means a Drawing
'consists' of an arbitrary number of Shapes
or to be more precise a Shape
is part of a Drawing
. When the lifetime of the owner (Drawing
) ends, then also the lifetime of Shape
will end:
// 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();
}
}
因为绘图之间的关系
和 Shape
是聚合 类型为 Shape $的实例c $ c>发生在所有者构造函数内部
(如果遇到 ,则在所有者对象外部)。
Because the relationship between Drawing
and Shape
is an aggregation the instantiation of the type Shape
occurs inside the owners constructor (opposed to outside the owner object in case of acquaintance).
该图显示的另一个关系是相识。 相识存在于类型 LineShape
和 Color
的对象之间。这意味着 LineShape
使用使用颜色
。 Color
将独立于其拥有的 LineShape
对象而生活。对象 CreationTool
和 LineShape
之间的虚线描述了实例化(创建)。这意味着 CreationTool
创建 LineShape
的实例。这是必需的,因为与 aggregation 熟人相对,它描述了两个对象的独立寿命。 颜色
可以在其他 Shape
对象之间共享。这要求 LineShape
的相关对象( Color
对象)在所有者外部(而不是所有者的内部)实例化。构造函数,例如在 aggregation 场景中):
The other relationship that is pictured by the diagram is the acquaintance. Acquaintance exist between the object of type LineShape
and Color
. This means a LineShape
uses a Color
. Color
will live independent from its owning LineShape
object. The dashed line between the objects CreationTool
and LineShape
describes an instantiation (create). This means that CreationTool
creates the instance of LineShape
. This is required since opposed to aggregation acquaintance describes an independent lifetime of both objects. Color
could be shared between other Shape
objects. This requires the related objects of LineShape
, the Color
object, to be instantiated outside the owner (and not inside the owner's constructor like in an aggregation scenario):
// 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
之间的关系是相识 实例化发生在所有者构造函数外部()(与所有者实例内部相反,例如在 aggregation 场景中)。这样,可以在多个所有者之间共享 Color
的单个实例。
Because the relationship between LineShape
and Color
is an acquaintance the instantiation occurs outside the owners constructor (opposed to inside the owner object like in an aggregation scenario). This way a single instance of Color
could be shared among multiple owners.
如代码示例所示两种关系(或一般的关系)都需要引用,指向相关对象的引用要存储在拥有的对象中。唯一的区别是查看在何处创建拥有的对象。这种情况将描述这种关系的特殊形式:关联对象是实例化为所有者的 outside (熟人)还是实例化了所有者的 inside (聚合)?
这意味着您可以通过查看构造函数(或实例化)来区分这两种类型的关系:是传递给构造函数的相关对象实例,还是所有者的设置方法( acquaintance )或所有者的构造函数是无参数的还是无参数的( aggregation )?
As you can see in the code examples both relations (or relations in general) require the reference, pointing to the related object(s), to be stored inside the owning object. The only difference is when looking at where the owned object was created. This circumstance will describe the special form of the relationship: was the related object instantiated outside the owner (acquaintance) or was it instantiated inside the owner (aggregation)? This means you can distinguish this two types of relationship by looking at the constructor (or instantiation): is the related object instance passed to the constructor or a setter method of the owner (acquaintance) or is the owner's constructor parameter-less or setter-less (aggregation)?
对于实例化,字段的要求是另一回事。可以说,当 CreationTool
实例化 LineShape
时,它不需要字段来存储对该对象的引用。但是,对于 Color
, CreationToolobject
可以存储对 Color $的引用。 c $ c>实例,以便在创建新的
LineShape
实例时重复使用(共享),因为实例是 Color $需要c $ c>来满足
LineShape
的构造函数。因此,如果首先需要一个字段来存储对创建者内部创建实例的引用,则该字段完全是可选的,并且取决于上下文。
For instantiation the requirement of a field is a different story. We can say that when CreationTool
instantiates LineShape
it does not need a field to store a reference to this object. But in case of the Color
the CreationToolobject
can store the reference to the Color
instance in a field in order to reuse it (share it) when creating new LineShape
instances, since an instance of Color
is needed to satisfy the constructor of LineShape
. So if a field to store the reference to the created instance inside the creator is required is totally optional in first place and depends on the context.
在此应提及要点是,如果是熟人,注入拥有对象实例的另一种方法是使用setter方法:
It should be mentioned at this point, that in case of acquaintance, another way to 'inject' the owned object instance is to use a setter method:
Color color = new Color();
LineShape shape = new LineShape();
shape.SetColor(color);
在可能的情况下,首选使用构造函数。
Using the constructor should be the prefered way whenever possible.
另一个说明,只是为了使其更加完整:当用于实现这种关系的语言具有自动内存管理(垃圾收集)功能时,生命周期控制就不再重要了。只要在M. Fowlers世界(或在UML世界的 aggregation )中,所有事物都成为熟人,因为只要存在对所拥有对象实例的任何引用(例如,公开实例(通过getter方法),垃圾收集器不会破坏该实例,并且它将继续存在-独立于所有者。
Another note, just to make it more complete: when the language used to implement such relationships has automatic memory management (garbage collection), then the aspect of lifetime controlling is no more relevant. Everything becomes acquaintance in M. Fowlers world (or aggregation in the UML world), since as long as there is any references stored to the owned object instance (e.g. when exposing the instance via a getter method), the garbage collector won't destruct this instance and it will continue to live - independent from the owner.