zoukankan      html  css  js  c++  java
  • UML类图五种关系与代码的对应关系

    转:

    UML类图中的五种关系的耦合强弱比较:依赖<关联<聚合<组合<继承

    一、依赖关系:

    (一)说明

    虚线+箭头

    可描述为:Uses a

    依赖是类的五种关系中耦合最小的一种关系。

    因为在生成代码的时候,这两个关系类都不会增加属性。

    (二)依赖关系图与代码的对应关系

    PS:依赖关系:Animal依赖于Water(动物依赖于水))

    [csharp] view plaincopyprint?
     
     
    1. Public class Animal()  
    2. {  
    3.         Public Animal(){}  
    4. }  
    5.   
    6. Public class Water()  
    7. {  
    8.         public Water(){}  
    9. }  

         可以看到生成的两个类的代码中什么都没有添加

    (三)思考:

    Animal类如何使用Water类呢?或者说依赖关系到底是如何体现的呢?

    1、表现形式1

    Water类是全局的,则Animal类可以调用它

    2、表现形式2

    Water类是 Animal类的某个方法中的变量,则Animal类可以调用它。

    [csharp] view plaincopyprint?
     
     
    1. Public class Animal {  
    2.       Public void Grownup() {  
    3.                Water water =null;  
    4.       }  
    5. }  

    注意1 Water类的生命期,它是Animal类的GrounUp方法被调用的时候,才被实例化

    注意2持有Water类的是Animal的一个方法而不是Animal,这点是最重要的!

    3、表现形式3

    Water类是作为Animal类中某个方法的参数或者返回值 

    [csharp] view plaincopyprint?
     
     
    1. Public Animal {  
    2.    Public Water Grownup(Waterwater) {  
    3.               return null;  
    4.       }  
    5. }  


    注意: Water类被Animal类的一个方法持有。生命期随着方法的执行结束而结束

    二、关联关系

    (一)说明

    实线+箭头

    可描述为:Has a

    关联关系用实线,表示类之间的耦合度比依赖强

    在生成代码的时候,关联关系的类会增加属性。

    (二)关联关系与代码的对应关系

          

               PS:Water类与Climate类关联(水与气候关联)。 

     

    [csharp] view plaincopyprint?
     
     
    1. Public classWater {  
    2.      public Climate m_Climate;  
    3.      public Water(){}  
    4. }  
    5.    
    6. Public class Climate {  
    7.      public Climate() {}  
    8. }  

    可见生成的代码中,Water类的属性中增加了Climate类。

    (三)关联关系的种类

    关联既有单向关联又有双向关联。

    1、单向关联: Water类和Climate类单向关联(如下图),则Water类称为源类,Climate类称为目标类。源类了解目标类的所有的属性和方法,但目标类并不了解源类的信息。

            

    2、双向关联:源类和目标类相互了解彼此的信息。如将Water类和Climate类之间改为双向关联。

     

    [csharp] view plaincopyprint?
     
     
    1. Public class Water {  
    2.     public Climate m_Climate;  
    3.     public Water(){}  
    4. }  
    5. Public class Climate {  
    6.     public Water m_Water;  
    7.     public Climate() {}  
    8. }  


    可见生成的代码中,两个类的属性都添加了!

    (四)思考:

    依赖关系和关联关系的区别在哪里?

    1、从类的属性是否增加的角度看

      1)发生依赖关系的两个类都不会增加属性。其中的一个类作为另一个类的方法的参数或者返回值,或者是某个方法的变量而已。

      2)发生关联关系的两个类,其中的一个类成为另一个类的属性,而属性是一种更为紧密的耦合,更为长久的持有关系。

    2、从关系的生命期角度看:

      1)依赖关系是仅当类的方法被调用时而产生,伴随着方法的结束而结束了。

      2)关联关系是当类实例化的时候即产生,当类销毁的时候,关系结束。相比依赖讲,关联关系的生存期更长。

    (五)关联关系的细化:聚合、组合

    1、说明

    1)聚合关系,用空心菱形加箭头表示

    2)组合关系,用实心菱形加箭头表示,类之间的耦合关系比聚合强!

    2聚合和组合都是关联关系的一种,到底如何区分二者呢?

    1)聚合和组合生成的代码

             (PS:此图表明雁群类是由大雁类聚合而成)

    [csharp] view plaincopyprint?
     
     
    1. Public classGooseGroup {  
    2.     public Goose goose;  
    3.     Public GooseGroup(Goose goose) {  
    4.               this.goose = goose;  
    5.        }  
    6. }  

        

            (PS:此图表明大雁类是由翅膀类组合而成)

    [csharp] view plaincopyprint?
     
     
    1. Public classGoose {  
    2.    public Wings wings;  
    3.    public Goose() {  
    4.        wings = new Wings();  
    5.     }  
    6. }  

    2)构造函数不同

              聚合类的构造函数中包含了另一个类作为参数。 雁群类(GooseGroup)的构 造函数中要用到大雁(Goose)作为参数传递进来。大雁类(Goose)可以脱离雁群类而独立存在。

             组合类的构造函数中包含了另一个类的实例化。 表明大雁类在实例化之前,一定要先实例化翅膀类(Wings),这两个类紧密的耦合在一起,同生共灭。翅膀类(Wings)是不可以脱离大雁类(Goose)而独立存在。

    3)信息的封装性不同。

             在聚合关系中,客户端可以同时了解雁群类和大雁类,因为他们都是独立的。

             在组合关系中,客户端只认识大雁类,根本就不知道翅膀类的存在,因为翅膀类被严密的封装在大雁类中。

     

    三、泛化

    (一)说明

    实线+箭头

    可描述为:Is a

    泛化也称继承,子类将继承父类的所有属性和方法,并且可以根据需要对父类进行拓展。

    (二)泛化关系与代码的对应关系

    PSBird类继承Animal类,鸟是一种动物)

    [csharp] view plaincopyprint?
     
     
    1. Class  Bird :Animal{  
    2. }  

    (三)思考:

    1、子类继承父类,真的是继承了父类的所有属性和方法吗?

          子类确实是继承了父类的所有属性和方法,只是对于父类的私有类型成员没有访问权限!访问就会报错!

    2、泛化和继承是一回事儿吗?

          子类继承父类,父类泛化子类。 这两个词是从不同的角度来说的! 

    3、为什么要多用组合少用继承?

           继承和组合各 有优缺点。

           类继承是在编译时刻静态定义的,且可直接使用,类继承可以较方便地改变父类的实现。但是类继承也有一些不足之处。首先,因为继承在编译时刻就定义了,所以无法在运行时刻改变从父类继承的实现。更糟的是,父类通常至少定义了子类的部分行为,父类的任何改变都可能影响子类的行为。如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。

            对象组合是通过获得对其他对象的引用而在运行时刻动态定义的。由于组合要求对象具有良好定义的接口,而且,对象只能通过接口访问,所以我们并不破坏封装性;只要类型一致,运行时刻还可以用一个对象来替代另一个对象;更进一步,因为对象的实现是基于接口写的,所以实现上存在较少的依赖关系。

    四、实现关系

           虚线+箭头

         (PSWideGoose类实现IFly接口。大雁实现飞翔的接口)

    [csharp] view plaincopyprint?
     
     
    1. Class WideGoose:Ifly{   
    2. }  

    实现关系重点理解接口的定义

        接口(interface),接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。

  • 相关阅读:
    MD5算法--网盘秒传
    无线网络定位算法综述
    android学习---异步任务(AsyncTask)
    python中局部变量的定义
    python3里函数怎么样使用元组或字典作为参数调用(复制他人博客)
    调试exynos4412—ARM嵌入式Linux—LEDS/GPIO驱动之一
    Linux入门之——安装虚拟机软件
    Linux学习方法之以始为终—Linux工作分类
    Linux基础系列—Linux内核源码目录结构
    Linux基础系列—Linux体系结构和Linux内核结构
  • 原文地址:https://www.cnblogs.com/nucdy/p/5748930.html
Copyright © 2011-2022 走看看