1. 依赖
5种关系中耦合最小的关系,使用虚线箭头表示
C++中有三种表现形式:
(1)Water作为全局类,Animal直接调用Water类,如:
class Water
{
};
Water *g_water = new Water;
class Animal
{
void Drink()
{
g_water;
}
};
(2)Water作为Animal类某个方法中的局部变量,如:
class Water
{
};
class Animal
{
void Drink()
{
//注意:持有Water类的是Drink方法,而不是Animal类。Drink被调用时Water类才被实例化
Water *water = new Water;
}
};
(3)Water类作为Animal类某个方法中参数或者返回值,如:
class Animal
{
void Drink(Water* pWater)
{
}
Water* Drink()
{
return new Water();
}
};
2. 关联
关联是比依赖更紧密的一种关系,使用实线箭头表示,由源类指向目标类,如:
Water为源类,Climate为目标类
C++中的表现形式为,Climate作为Wate类的一个属性,如:
class Climate
{};
class Water
{
Climate m_climate;
};
关联分为单向关联和双向关联,以上的例子为单向关联,双向关联表示双方类都将对方作为属性,如:
class Water;
class Climate
{
Water* m_water;
};
class Water
{
Climate* m_climate;
};
依赖与关联的区别:
从是否是类的属性来看,依赖关系的类并不作为双方的一个属性(即成员),仅作为一个类的某个方法的参数、返回值或变量。而关联关系的类,其中一个类成为另一个类的属性(成员),因此关联关系更紧密。
从生命期来看,依赖关系仅当类的方法被调用时才产生,方法调用结束,依赖关系即结束。而关联关系在类的实例化时即产生,类被销毁后才结束。
关联关系又分为聚合和组合两种关系,分为聚合和组合,C++中代码的区别如下,
class Wings {};
class Goose
{
public:
Goose() {
m_wings = new Wings;//组合关系
}
private:
Wings* m_wings;
};
class GooseGroup
{
public:
GooseGroup(Goose *pGoose) :m_goose(pGoose) {}//聚合关系
private:
Goose* m_goose;
};
UML关系图表示如下(空心菱形为聚合,实心菱形为组合,实心表示更紧密,菱形在源类端)
其中,Goose(源)与Wings(目标)为组合关系,GoogeGroup(源)与Goose(目标)为聚合关系,具体区别为:
(1)构造函数不同
聚合关系的源类(GooseGroup)的构造函数包含了目标类(Goose)的参数,而组合关系的源类(Goose)的构造函数里要实例化目标类(Wings)。
即在聚合关系里,源类与目标类是可以分开独立存在的,不需要在源类里对目标里做实例化,可以在类外做实例化。而组合关系里,源类被实例化之前,必须先实例化目标类,即目标类无法脱离源类独立存在,两者共生共灭。
(2)信息的封装性不同
在聚合关系里,客户端可以同时了解到Goose类与GooseGroup类,它们是独立存在的。而在组合关系里,客户端只了解到Goose类,而根本不知道Wings类的存在,因为Wings类被封装在Goose类里。