UML中的关联关系

来源:互联网 发布:js中实现继承 编辑:程序博客网 时间:2024/05/21 08:04
我们在《UML的概述与详解》中已经讲到关联关系,但是对他们之间的理解还是不是很透彻,尤其是针对关联、聚合、合成这几个之间的关系与区别,分不清。这里下面专门来讲这几个东东。

一、首先,我们先看一下关联关系的分类。
       从前面的《UML的概述与详解》中可以看到,关系关系可以分为6类:1.依赖;2.关联;3.聚合;4.合成;5.泛化;6.实现;
其中,对于“泛化”与“实现”这两个还是比较好理解的。 “泛化”体现了Java中的extend关键字;而“实现”体现了Java中的implements关键字。对于前面的4种,我们在下面做进一步的探讨。

二、再看一下这几者之间的区别。
       1. 依赖(Dependency)
       依赖表示的是一个类的定义依赖于另一个类的定义,表示是类与类之间的连接(注意这里指的是连接)。依赖关系仅仅描述了类与类之间的一种使用与被使用的关系。我们看看它转化到Java中的展现就比较好理解了。
       体现:体现为局部变量,方法/函数的参数或者是对静态方法的调用。
       注意依赖与后面的另外三种不同的是:后面三种(关联,聚合,合成)体现到Java中表现为类的成员变量,而依赖不是,仅仅是局部变更或是方法参数或是静态方法的调用。从这一点上就可以明白上面说的“描述了类与为之间的使用与被使用的关系”的意思了,后面三种则都存在这种成员变量的引用的关系了。
       依赖的图示:虚线+箭头,如下图D:
       图D
          
       从上图,还可以看出依赖的另一种情况,如上图,Employee类中甚至完全没有引用到Calculator类,Employee类在方法calcSalary()方法中使用的参数是CalculatorStrategy对象,这在设计模式中是一个策略模式,CalculatorStrategy是一个抽象类或是一个接口,虽然方法中没有直接引用Calculator类,而是CalculatorStrategy对象,但在实际调用calcSalary()方法时,传递给该方法的实例则不可能是CalculatorStrategy对象(因为CalculatorStrategy是抽象类,不能实例化),应该是Calculator类,从而两者产生依赖关系。因此依赖关系有可能是在静态代码中甚至体现不出来,但在实际发生作用时,两个类出现这种相互连接、依赖、使用的关系。
       2.关联(Association)
      如《UML的概述与详解》中的描述,它表示的是两个实体的结构化关系之间的相互联接。
      注意点:1.这里是类的结构化,表示在结构上就是相互连接,可以理解为在代码层面便是相互声明,体现为类的实例变量;
                    2.箭头是可选的,它用于指定导航能力。即是说关联总是被假定是双向的,除非你画了箭头,来表示这种关联是一种单向的关联,否则,没有画箭头,则暗示是一种双向导航的能力。
                    3.双向关联意味着,两个类彼此知道它们间的联系;而加了箭头的单向关联则意味着只有一个类知道这种联系的存在,而另一个类则对此关联毫无所知。
      体现:体现为类中的实例变量的引用。
      图示:实线+箭头(可选),如下图E:
      图E
      
      3.聚合(Aggregation)
      首先要知道一点,“
合成”是聚合的一种特殊的形式,而“聚合”本身是“关联”的一种特殊的形式。我们先来看看什么是聚合。
      
聚合是一种特别类型的关联,用于描述“总体到局部”的关系。在基本的聚合关系中, 部分类 的生命周期独立于 整体类 的生命周期。
      举例来说,我们可以想象,车 是一个整体实体,而 车轮 轮胎是整辆车的一部分。轮胎可以在安置到车时的前几个星期被制造,并放置于仓库中。在这个实例中,Wheel类实例清楚地独立地Car类实例而存在。然而,有些情况下, 部分类的生命周期并不独立于 整体类 的生命周期 -- 这称为合成聚合。举例来说,考虑公司与部门的关系。 公司和部门都建模成类,在公司存在之前,部门不能存在。这里Department类的实例依赖于Company类的实例而存在。
       从上面的例子能明白基本聚合与合成聚合之间的区别之后,我们再分别来探讨两者的表示。
       基本聚合
       体现:体现为类中的实例变量的引用。
       聚合关系的关联指出,某个类是另外某个类的一部分。在一个聚合关系中,子类实例可以比父类存在更长的时间。为了表现一个聚合关系,你画一条从父类到部分类的实线,并在父类的关联末端画一个未填充棱形。图F显示车和轮胎间的聚合关系的例子。
      图F
     
      从上面的讨论可以看出,聚合与关联相比,暗示着一种整体与局部的关系。关联通常意义上暗示着这两个类在概念上处于同一个级别,而聚合则暗示着 整体类 在概念上要比 局部类 高出一个级别。事实上他们两者的区别纯粹是概念上的,而严格反映到语义上,都是体现为类中的实例变量的引用。聚合还暗示着实例图中不存在回路。换言之,只能是一种单向关系。
     4.合成(Composition)
     
合成聚合关系是聚合关系的一种特殊形式,表示子类实例的生命周期依赖于父类实例的生命周期。在图G中,显示了Company类和Department类之间的组合关系,注意组合关系如聚合关系一样绘制,不过这次菱形是被填充的。
     体现:体现为类中的实例变量的引用。
     图G
    
     在上图中的关系建模中,一个Company类实例至少总有一个Department类实例。因为关系是组合关系,当Company实例被移除/销毁 时,Department实例也将自动地被移除/销毁。组合聚合的另一个重要功能是部分类只能与父类的实例相关(举例来说,我们例子中的Company 类)。
  

       另外,我们来看一种反射关联
       现在我们已经讨论了所有的关联类型。就如你可能注意到的,我们的所有例子已经显示了两个不同类之间的关系。然而,类也可以使用反射关联与它本身相关 联。起先,这可能没有意义,但是记住,类是抽象的。图H显示一个Employee类如何通过manager / manages角色与它本身相关。当一个类关联到它本身时,这并不意味着类的实例与它本身相关,而是类的一个实例与类的另一个实例相关。
       图H:

  

  图H描绘的关系说明一个Employee实例可能是另外一个Employee实例的经理。然而,因为“manages”的关系角色有%200..*的多重性描述;一个雇员可能不受任何其他雇员管。

原创粉丝点击