一、关联关系:一个对象知道另一个对象的存在,该对象持有另一个对象的指针或者引用
class X
{
public:
X(Y* _ptrY):ptrY_(_ptrY) {}
void setY(Y *y) { ptrY_ = y;}
void f() { ptrY_->foo();}
private/public:
Y* ptrY_; // X类持有Y的一个指针,可据此调用Y中的成员方法
}
二、依赖关系(dependency):
当类Y与类X彼此独立,而类Y是类X成员函数的一个参数,或者X中成员函数的一个局部变量
class X
{
...
void f1(Y y) { ...; y.foo(); }
void f2(Y& y) { ...; y.foo(); }
void f3(Y* y) { ...; y->foo(); }
void f4() { ...; Y y; y.foo(); }
void f5() { Y::staticFoo();}
...
}
三、聚合关系(Aggregation):
聚类发生的场景是:一个类是另一个类的集合或者容器,但被包含的类与容器本身并不具备相同的生命期,也就是容器销毁时,其包含的内容未必。关联(association)与聚合(aggregation)的不同之处在于,关联关系不存在一个明确的容器包含另外一个类。比如汽车和轮胎的关系,就是一种聚合关系,汽车包含着轮胎的集合,汽车的销毁,轮胎仍然可以存在。
class Window
{
public:
//...
private:
vectr<Shape*> ptrShapes;
}
四、组合关系(Composition)
组合(composition)是聚合(Aggregation)的增强版。组合和聚合的根本不同在于类与其所持有元素的是否具有相同的生命期,要求必须相同是一种组合关系。
class Circle
{
private:
...
Point center_;
...
}
class X
{
...
Y y; // composition, 相同的生命期,
// 如何是引用或者指针类型,则是关联类型,是一种弱联系
Y b[10]; // 0...10, composition
}
class X
{
X() { a = new Y[10]; }
~X() { delete[] a;}
...
Y *a; // 0...10, composition,X对象析构时,必须对a进行释放
}
五、继承(泛化)
类间的继承关系表达的是一种derived class B is a base class A
从生命周期来看,关联时大家的生命周期大家都管不着,聚合时部分的生命周期长于整体,组合时整体与部分共存亡(整体的生命周期比部分略长一点)。
六、关联(association) 聚合(aggregation) 组合(composition)的区别
========================================================
三者之间在c++中都是体现为 "has a" 的关系
在C++中,从实现的角度讲,关联和聚合可以表示为:
class A {...}
class B { A* a; .....}
即类B包含类A的指针;(因为在关联和聚合中,A B的生命周期都是分开的)
而组合可表示为:
class A {...}
class B { A a; ...}
即类B包含类A的对象。(因为在组合中,A 和 B 的生命周期是一致的,有B就有A,B是大整体,A是B的一部分,如果B没了,那么A也没了),也可以用指针的方式表示,关键看生命周期
那么,关联和聚合的区别在哪里呢?
从语法角度上来说,两者没有区别。
两者的区别在于语义:关联代表 A 和 B 是平等的;聚合代表 A 是 B 的一部分(但是即使这样,AB的生命周期仍然是分开的,生命周期是一致的是组合)
七、组合与聚合的区别
1.组合方式一般代码会这样写
A类的构造方法里创建B类的对象,也就是说,当A类的一个对象产生时,B类的对象随之产生,当A类的这个对象消亡时,它所包含的B类的对象也随之消亡。
2.聚合方式一般代码会这样写:
A类的对象在创建时不会立即创建B类的对象,而是等待一个外界的对象传给它
--------------------------------------------------------------------
对c++,形如:
class B1;
class B2;
class B3;
class A
{
B1 b1;
B2& b2;
B3* b3;
};
B1,B2,B3都是部分类。
B1与A的关系是组成关系。
B2、B3与A的关系是聚合还是组成要根据这一条:部分类是否能脱离整体类而存在。
在这里可以理解他们的生命周期是否同步。
如果b2,b3是通过外部传入的,形如:
class A
{
public:
A(B3* b3)
{
m_b3 = b3);
}
private:
B3* m_b3;
};
main()
{
B2 bbb;
A a(&bbb);
}
bbb并不会因为a的消亡而消亡。那么就是聚合关系。
反之,如果
m_b3是在A的构造函数new,在A的析构函数delete,两者生命周期一样,那么就是组成关系。
引用的情况类似。