类之间的关系在大体上分为两种,一种是纵向的,另一种是横向的。
一、纵向的就是继承,它是OO
的三个特征之一。
在UNL
中称作:
泛化(
Generalization)
表示为:实线+空心三角形
实现(Realization)
表示为: 虚线+空心三角形
u
泛化
泛化关系:
是一种继承关系,
表示一般与特殊的关系,
它指定了子类如何特化父类的所有特征和行为。表示类与类之间的继承关系,接口与接口之间的继承关系。一般化的关系是从子类指向父类的,与继承或实现的方法相反。
// Animal.h
class CAnimal
{
public:
// implement
virtual HRESULT EatSomething()
{
// Do something
}
};
// Tiger.h
#include "Animal.h"
class CTiger : public CAnimal
{
// Do something
};
class CAnimal
{
public:
// implement
virtual HRESULT EatSomething()
{
// Do something
}
};
// Tiger.h
#include "Animal.h"
class CTiger : public CAnimal
{
// Do something
};
u
实现
实现关系
:
是一种类与接口的关系
,
表示类是接口所有特征和行为的实现。
// Animal.h
class CAnimal
{
public:
// interface
virtual HRESULT EatSomething() = 0;
};
// Tiger.h
#include "Animal.h"
class CTiger : public CAnimal
{
// Do something
};
注: 泛化和实现的区别就在于子类是否继承了父类的实现, 如有继承则关系为泛化, 反之为实现.
class CAnimal
{
public:
// interface
virtual HRESULT EatSomething() = 0;
};
// Tiger.h
#include "Animal.h"
class CTiger : public CAnimal
{
// Do something
};
注: 泛化和实现的区别就在于子类是否继承了父类的实现, 如有继承则关系为泛化, 反之为实现.
二、横向关系,按UML
关系分为4
种,
依赖(
Dependency)
,表示为:--------
à
即虚线+
箭头
关联(
Association)
,
表示为:
实线+
箭头
聚合(
Aggregation)
,表示为:
空心菱形+
实线
组合(
Composition)
,表示为:
实心菱形+
实线
它们的强弱关系是:依赖
<
关联
<
聚合
<
组合
,
u
依赖
依赖就是某个对象的功能依赖于另外的某个对象,而被依赖的对象只是作为一种工具在使用,而并不持有对它的引用。
对于两个相对独立的对象,当一个对象负责构造另一个对象的实例,或者依赖另一个对象的服务时,这两个对象之间主要体现为依赖关系。
是一种使用的关系
,
即一个类的实现需要另一个类的协助
,
所以要尽量不使用双向的互相依赖
.
类
A
使用到了另一个类
B
,而这种使用关系是具有偶然性的、、临时性的、非常弱的,但是
B
类的变化会影响到
A
;比如某人要过河,需要借用一条船,此时人与船之间的关系就是依赖;表现在代码层面,为类
B
作为参数被类
A
在某个
method
方法中使用;
// Car.h
class CCar
{
// Do something
};
class CCar
{
// Do something
};
// Person.h
#include "Car.h"
class CPerson
{
void MoveFast(CCar &pCar);
};
上图中人的快速移动需要有车的协助, 但是这种依赖是比较弱的, 就是人也可以不用车而用其他工具, 与关联不同的是人不必拥有这辆车只要使用就行.
u
关联
关联就是某个对象会长期的持有另一个对象的引用,而二者的关联往往也是相互的。关联的两个对象彼此间没有任何强制性的约束,只要二者同意,可以随时解除关系或是进行关联,它们在生命期问题上没有任何约定。被关联的对象还可以再被别的对象关联,所以关联是可以共享的。
他体现的是两个类、或者类与接口之间语义级别的一种强依赖关系,比如我和我的朋友;这种关系比依赖更强、不存在依赖关系的偶然性、关系也不是临时性的,一般是长期性的,而且双方的关系一般是平等的、关联可以是单向、双向的;表现在代码层面,为被关联类
B
以类属性的形式出现在关联类
A
中,也可能是关联类
A
引用了一个类型为被关联类
B
的全局变量;
双向关联是指双方都拥有对方的引用
,
都可以调用对方的公共属性和方法:
程序代码
// Husband.h
#include "wife.h"
class CHusband
{
public:
CWife* pWife;
};
// Wife.h
#include "Husband.h"
class CWife
{
public:
CHusband* pHuband;
};
上图中丈夫和妻子是比较公平的关系, 都可以使用对方公共的属性.
单向关联是指只有某一方拥有另一方的引用
,
这样只有拥有对方者可以调用对方的公共属性和方法
.
如下
程序代码
// Husband.h
class CHusband
{
public:
int nMoney;
void GoShopping();
};
// Wife.h
#include "Husband.h"
class CWife
{
public:
CHusband* pHuband;
};
上图中妻子拥有丈夫, 可以使用对方的属性, 比如钱, 可以让对方做能做的事, 比如去买东西.
自身关联是指拥有一个自身的引用
程序代码
// SingleMan.h
class CSingleMan
{
public:
CSingleMan *pSingleMan;
};
u
聚合
聚合是强版本的关联。它暗含着一种所属关系以及生命期关系。被聚合的对象还可以再被别的对象关联,所以被聚合对象是可以共享的。虽然是共享的,聚合代表的是一种更亲密的关系。
聚合是整体与部分的关系,且部分可以离开整体而存在,如,车和轮胎是整体和部分的关系,轮胎离开车还可以存在。
是关联关系的一种特例,他体现的是整体与部分、拥有的关系,即
has-a
的关系,此时整体与部分之间是可分离的,他们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享;比如计算机与
CPU
、公司与员工的关系等;表现在代码层面,和关联关系是一致的,只能从语义级别来区分
// Car.h
#include "Tyre.h"
class CCar
{
public:
CTyre cTyre;
};
// Tyre.h
#include "Car.h"
class CTyre
{
// Do something
};
#include "Tyre.h"
class CCar
{
public:
CTyre cTyre;
};
// Tyre.h
#include "Car.h"
class CTyre
{
// Do something
};
u
组合
组合是关系当中的最强版本,它直接要求包含对象对被包含对象的拥有以及包含对象与被包含对象生命期的关系。被包含的对象还可以再被别的对象关联,所以被包含对象是可以共享的,然而绝不存在两个包含对象对同一个被包含对象的共享。
组合是整体与部分的关系,但部分不能离开整体而存在,如,公司和部门是整体与部分的关系,没有公司就不存在部门。
组合也是关联关系的一种特例,他体现的是一种
contains-a
的关系,这种关系比聚合更强,也称为强聚合;他同样体现整体与部分间的关系,但此时整体与部分是不可分的,整体的生命周期结束也就意味着部分的生命周期结束;比如你和你的大脑;表现在代码层面,和关联关系是一致的,只能从语义级别来区分;
// Company.h
#include "Department.h"
class CCompany
{
public:
CDepartment cDepartment;
};
// Tyre.h
#include "Company.h"
class CDepartment
{
// Do something
};
#include "Department.h"
class CCompany
{
public:
CDepartment cDepartment;
};
// Tyre.h
#include "Company.h"
class CDepartment
{
// Do something
};
释义:组合关系就是整体与部分的关系,部分属于整体,整体不存在,部分一定不存在,然而部分不存在整体是可以存在的,说的更明确一些就是部分必须创生于整体创生之后,而销毁于整体销毁之前。部分在这个生命期内可以被其它对象关联甚至聚合,但有一点必须注意,一旦部分所属于的整体销毁了,那么与之关联的对象中的引用就会成为空引用,这一点可以利用程序来保障。心脏的生命期与人的生命期是一致的,如果换个部分就不那么一定,比如阑尾,很多人在创生后的某个时间对其厌倦便提前销毁了它,可它和人类的关系不可辩驳的属于组合。在
UML
中存在一种特例,就是允许被包含对象在包含对象销毁前转移给新的对象,这虽然不自然,但它给需要心脏移植的患者带来了福音。
Ø
关联与聚合的区别
(1)
关联关系所涉及的两个对象是处在同一个层次上的。比如人和自行车就是一种关联关系,而不是聚合关系,因为人不是由自行车组成的。
聚合关系涉及的两个对象处于不平等的层次上,一个代表整体,一个代表部分。比如电脑和它的显示器、键盘、主板以及内存就是聚集关系,因为主板是电脑的组成部分。
(2)
对于具有聚集关系(尤其是强聚集关系)的两个对象,整体对象会制约它的组成对象的生命
周期。部分类的对象不能单独存在,它的生命周期依赖于整体类的对象的生命周期,当整体消失,部分也就随之消失。比如张三的电脑被偷了,那么电脑的所有组件
也不存在了,除非张三事先把一些电脑的组件(比如硬盘和内存)拆了下来。
Ø
举一个简单的例子:
一个图书馆可以有十万本书,也可以一本也没有。但空的图书馆还是图书馆。这是聚合。
一个车(我们平常能看到的普通的交通工具车)有轮子,有的车是四轮子的,有的车是三轮的,自行车是二轮的,还有独轮车,但车至少要有一个轮子,不然就不是车。这是组合关系。
类之间的关系种类: Generalization(
泛化)
,Dependency(
依赖关系)
、Association(
关联关系)
、Aggregation(
聚合关系)
、Composition(
合成关系)
。
其中Aggregation( 聚合关系) 、Composition( 合成关系) 属于Association( 关联关系) ,是特殊的Association 关联关系。Generalization( 泛化) 表现为继承或实现关系(is a) 。具体形式为类与类之间的继承关系,接口与接口之间的继承关系,类对接口的实现关系 。
其中Aggregation( 聚合关系) 、Composition( 合成关系) 属于Association( 关联关系) ,是特殊的Association 关联关系。Generalization( 泛化) 表现为继承或实现关系(is a) 。具体形式为类与类之间的继承关系,接口与接口之间的继承关系,类对接口的实现关系 。
Association 关联 系表现为变量(has a ) 。类与类之间的联接,它使一个类知道另一个类的属性和方法。例如如果A 依赖于B ,则B 体现为A 的全局变量。关联关系有双向关联和单向关联。双向关联:两个类都知道另一个类的公共属性和操作。单向关联:只有一个类知道另外一个类的公共属性和操作。大多数关联应该是单向的,单向关系更容易建立和维护,有助于寻找可服用的类。
Aggregat ion(
聚合关系)
是关联关系的一种,是强的关联关系。聚合关系是整体和个体的关系。普通关联关系的两个类处于同一层次上,而聚合关系的两个类处于不同的层次,一个是整体,一个是部分。同时,是一种弱的“拥有”关系。体现的是A
对象可以包含B
对象,但B
对象不是A
对象的组成部分。具体表现为,如果A
由B
聚合成,表现为A
包含有B
的全局对象,但是B
对象可以不在A
创建的时刻创建。
Composition(
组合关系)
是关联关系的一种,是比聚合关系强的关系。它要求普通的聚合关系中代表整体的对象负责代表部分的对象的生命周期。Composition(
组合关系)
是一种强的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期一致。如果A
由B
组成,表现为A
包含有B
的全局对象,并且B
对象在A
创建的时刻创建。
Dependency(
依赖关系)
表现为函数中的参数(use a)
。是类与类之间的连接,表示一个类依赖于另一个类的定义,其中一个类的变化将影响另外一个类。例如如果A
依赖于B
,则B
体现为局部变量,方法的参数、或静态方法的调用。
转载于:https://blog.51cto.com/0503521/1051797