聚合(aggregation)和相识(acquaintance)
@(Design Patterns)[C++, 设计模式]
在《模式设计》一书中,聚合与相识的定义分别如下,
聚合 意味着一个对象拥有另一个对象或对另一个对象负责。一般我们称一个对象包含另一个对象或者是另一个对象的一部分。
相识 意味着一个对象仅仅知道另一个对象。有时相识也被称为“关联”或“引用”关系。相识的对象可能请求彼此的操作,但是它们不为对方负责。
CSDN讨论社区的一个例子能够很好的说明两者的区别。
聚合
聚合对象包容了被聚合对象,或者说,聚合对象控制被聚合对象的生命期,在C++中,如果被聚合对象在聚合对象中是以成员变量的形式存在的,那么二者同生同 死。如果被聚合对象是以其指针方式被聚合的,它有可能是延迟构造并可能是提前析构的,即被聚合对象诞生于聚合对象之后,死于聚合对象之前。
class Aggregatee //被聚合对象 {
}; class Aggregator //聚合对象 {
private:
Aggregatee m_agg1; //被聚合对象与聚合对象同生死
Aggregatee* m_pAgg2;
Aggregatee* m_pAgg3;
public:
Aggregator()
{
m_pAgg2 = new Aggregatee(); //被聚合对象与聚合对象同时诞生m_pAgg3 = NULL;
} ~Aggregator()
{
if( m_pAgg2 != NULL )
{
delete m_pAgg2; //被聚合对象与聚合对象同时死亡
m_pAgg2 = NULL;
}if( m_pAgg3 != NULL )
{
delete m_pAgg3; //防止用户忘记调用Destroy()函数造成内存泄露
m_pAgg3 = NULL;
}
} void Initilize()
{
m_pAgg3 = new Aggregatee(); //延迟构造,被聚合对象在聚合对象之后诞生
} void Destroy()
{
if( m_pAgg3 != NULL )
{
delete m_pAgg3;
m_pAgg3 = NULL; //提前析构,被聚合对象在聚合对象之前死亡
}
}
};
Aggregator 的实例和成员m_agg1,m_pAgg2,m_pAgg3之间的关系就是聚合/组合的关系。它们3个的不同之处正好说明了前面所说的不同点。
相识
class A { }; class B { private: A* m_pA; public: B(A* pA = NULL) { m_pA = pA; } void Attach(A* pA) {ASSERT(pA); //如果pA == NULL,则中断程序 m_pA = pA; } void Detach() { m_pA = NULL; } ~B() { Detach(); } };
class B
的实例和成员m_pA
所指向的对象之间的关系即为相识关系。构造B时如果提供的参数pA
不为NULL
,则B的实例即与参数pA
所指向的对象之间建立了 相识关系。如果参数pA
为NULL
,还可以通过Attach建立相识关系,此时一般不允许Attach
函数的参数pA
为NULL
。通过Detach
解除相 识关系。
综上
- 聚合关系是说,一个对象的构造和析构都在另一个对象里面进行,聚合对象对被聚合对象的实现负责。
- 相识关系是说,一个对象对另一个对象具有引用访问方式,而两个对象本身独立负责自身的构造和析构。