UML设计中的箭头详解

1.关联-属性指针-associate

(1)双向关联-相互关联,相互把对方作为自己的指针

image

C1-C2:指双方都知道对方的存在,都可以调用对方的公共属性和方法。 在GOF的设计模式书上是这样描述的:虽然在分析阶段这种关系是适用的,但我们觉得它对于描述设计模式内的类关系来说显得太抽象了,因为在设计阶段关联关 系必须被映射为对象引用或指针。对象引用本身就是有向的,更适合表达我们所讨论的那种关系。所以这种关系在设计的时候比较少用到,关联一般都是有向的。 使用ROSE 生成的代码是这样的:

class C1
...{
public:
C2* theC2;

};

class C2
...{
public:
C1* theC1;

};

双向关联在代码的表现为双方都拥有对方的一个指针,当然也可以是引用或者是值。

(2)单向关联-关联到它就把它当做自己的属性指针

image

C3->C4:表示相识关系,指C3知道C4,C3可以调用C4的公共属性和方法。没有生命期的依赖。一般是表示为一种引用。 生成代码如下:

class C3
{
public:
C4* theC4;

};
class C4
{
};

单向关联的代码就表现为C3有C4的指针,而C4对C3一无所知。

(3)自身关联(反身关联)-关联到自己,就是把自己当做属性指针

image

自己引用自己,带着一个自己的引用。 代码如下:

class C14
{
public:
C14* theC14;

};

就是在自己的内部有着一个自身的引用。

2.依赖-依赖到它,就把它的指针或引用,作为自己的函数形参-dependency

(1)单向依赖

image

依赖: 指C5可能要用到C6的一些方法,也可以这样说,要完成C5里的所有功能,一定要有C6的方法协助才行。C5依赖于C6的定义,一般是在C5类的头文件中包含了C6的头文件。ROSE对依赖关系不产生属性。 注意,要避免双向依赖。一般来说,不应该存在双向依赖。 ROSE生成的代码如下:

// C5.h

include "C6.h"

class C5
{
public:

void Func(C6 *pC6Obj);

};

// C6.h

include "C5.h"

class C6
{

}

(2)双向依赖

双向依赖关系图没有看到标准的画法,知道时候补上。

那依赖和聚合\组合、关联等有什么不同呢? 关联是类之间的一种关系,例如老师教学生,老公和老婆,水壶装水等就是一种关系。这种关系是非常明显的,在问题领域中通过分析直接就能得出。 依赖是一种弱关联,只要一个类用到另一个类,但是和另一个类的关系不是太明显的时候(可以说是“uses”了那个类),就可以把这种关系看成是依赖,依赖 也可说是一种偶然的关系,而不是必然的关系,就是“我在某个方法中偶然用到了它,但在现实中我和它并没多大关系”。例如我和锤子,我和锤子本来是没关系 的,但在有一次要钉钉子的时候,我用到了它,这就是一种依赖,依赖锤子完成钉钉子这件事情。

组合是一种整体-部分的关系,在问题域中这种关系很明显,直接分析就可以得出的。例如轮胎是车的一部分,树叶是树的一部分,手脚是身体的一部分这种的关系,非常明显的整体-部分关系。 上述的几种关系(关联、聚合/组合、依赖)在代码中可能以指针、引用、值等的方式在另一个类中出现,不拘于形式,但在逻辑上他们就有以上的区别。 这里还要说明一下,所谓的这些关系只是在某个问题域才有效,离开了这个问题域,可能这些关系就不成立了,例如可能在某个问题域中,我是一个木匠,需要拿着 锤子去干活,可能整个问题的描述就是我拿着锤子怎么钉桌子,钉椅子,钉柜子;既然整个问题就是描述这个,我和锤子就不仅是偶然的依赖关系了,我和锤子的关 系变得非常的紧密,可能就上升为组合关系(让我突然想起武侠小说的剑不离身,剑亡人亡...)。这个例子可能有点荒谬,但也是为了说明一个道理,就是关系 和类一样,它们都是在一个问题领域中才成立的,离开了这个问题域,他们可能就不复存在了

3.组合/聚合-属性对象-composite/aggreate

(1)组合-自己是实心的,去组合它,把它当做自己的属性对象,只是被组合的类不会单独存在(自己构造函数中使用)

image

组合(也有人称为包容):一般是实心菱形加实线箭头表示,如上图所示,表示的是C8被C7包容,而且C8不能离开C7而独立存在。但这是视问题域而定的, 例如在关心汽车的领域里,轮胎是一定要组合在汽车类中的,因为它离开了汽车就没有意义了。但是在卖轮胎的店铺业务里,就算轮胎离开了汽车,它也是有意义 的,这就可以用聚合了。在《敏捷开发》中还说到,A组合B,则A需要知道B的生存周期,即可能A负责生成或者释放B,或者A通过某种途径知道B的生成和释 放。 他们的代码如下:

class C7
{
public:
C8 theC8;

};

class C8
{
};

可以看到,代码和聚合是一样的。具体如何区别,可能就只能用语义来区分了。

(2)聚合-自己空心的,去聚合它,把它当做自己的属性对象,被聚合的类可以单独存在(自己构造函数中不使用)

当类之间有整体-部分关系的时候,我们就可以使用组合或者聚合。
image

聚合:表示C9聚合C10,但是C10可以离开C9而独立存在(独立存在的意思是在某个应用的问题域中这个类的存在有意义。这句话怎么解,请看下面组合里的解释)。 代码如下:

class C9
{
public:
C10 theC10;

};

class C10
{

};

//总结聚合和组合:

问题域的语义上:组合中被组合类单独存在没有意义; 聚合中被聚合类在可以有单独存在的意义。

生命期上:组合中必须要负责被组合类的生命期; 聚合中可不负责被聚合类的声明期,可以由外部程序来创建和消亡(可用赋值)。

4.泛化和实现 derived/implement

(1)继承(Derived)-子对象指向父对象

image

泛化关系:如果两个类存在泛化的关系时就使用,例如父和子,动物和老虎,植物和花等。 ROSE生成的代码很简单,如下:

include "C11.h"

class C12 : public C11
{
};

(2)接口实现(implement)

  1. 实现关系指定两个实体之间的一个合约。换言之,一个实体定义一个 合约 ,而另一个实体保证履行该 合约 。
    image

浅谈UML中的聚合与组合(两者之间的区别)

大家都知道UML的类图中一般包含五种关系即 关联 聚合 组合 泛化 依赖 有些人可能会感觉组合跟聚合有点难区分 说难其实是相对其他几种关系而言 实际上想分清这两种关系一点也不难

聚合跟组合其实都属于关联 只不过它们是两种特殊的关联 因为本是同根生 所以它们之间难免会有相似之处 下面让我们一起来看一下它们之间有何不同

聚合与组合的概念相信不用我在此赘述大家就已经了解了 下面直接上例子

程老师的《大话》里举大那个大雁的例子很贴切 在此我就借用一下 大雁喜欢热闹害怕孤独 所以它们一直过着群居的生活 这样就有了雁群 每一只大雁都有自己的雁群 每个雁群都有好多大雁 大雁与雁群的这种关系就可以称之为聚合 另外每只大雁都有两只翅膀 大雁与雁翅的关系就叫做组合 有此可见 聚合的关系明显没有组合紧密 大雁不会因为它们的群主将雁群解散而无法生存 而雁翅就无法脱离大雁而单独生存——组合关系的类具有相同的生命周期

聚合关系图:

image.png

组合关系图:

image.png

从从代码上看这两种关系的区别在于:

构造函数不同

雁群类:

public  class GooseGroup
{
    public Goose goose;

    public GooseGroup(Goose goose)
    {
        this.goose = goose;
    }
}

大雁类:

public class Goose
{
    public Wings wings;

    public Goose()
    {
        wings=new Wings();
    }
}

聚合关系的类里含有另一个类作为参数

雁群类(GooseGroup)的构造函数中要用到大雁(Goose)作为参数把值传进来 大雁类(Goose)可以脱离雁群类而独立存在

组合关系的类里含有另一个类的实例化

大雁类(Goose)在实例化之前 一定要先实例化翅膀类(Wings) 两个类紧密耦合在一起 它们有相同的生命周期 翅膀类(Wings)不可以脱离大雁类(Goose)而独立存在

浅谈UML中的聚合与组合
UML设计中的箭头详解

你可能感兴趣的:(UML设计中的箭头详解)