欢迎光临
我们一直在努力

UML类图五种关系与代码的对应关系

五种关系的耦合强弱比较:依赖<关联<聚合<组合<继承
一、依赖关系:

        1.说明:虚线+剪头,可描述为Use a        
         
依赖是类的5种关系中耦合最小的一种关系,因为在生成代码的时候,这两个关系类都不会增加属性
        2.依赖关系图与代码的对应关系
        

  1. Public class Animal()  
  2. {  
  3.         Public Animal(){}  
  4. }  
  5.   
  6. Public class Water()  
  7. {  
  8.         public Water(){}  
  9. }  

        可以看到生成的两个类的代码中什么都没有添加
        3.思考
        Animal类是如何使用Water类的呢?或者说依赖关系到底是如何体现的呢?

  • water类是全局的,则animal类可以调用它
  • water类是animal类的某个方法中的变量,则animal类可以调用它

  1. Public class Animal {  
  2.       Public void Grownup() {  
  3.                Water water =null;  
  4.       }  
  5. }  

        注意1:water类的生命后期,它是当animal类的grounUp类方法被调用时才被实例化
        注意2:持有water类的是animal的一个方法而不是animal类

  • water类是作为animal类中某个方法的参数或者返回值

  1. Public Animal {  
  2.    Public Water Grownup(Waterwater) {  
  3.               return null;  
  4.       }  
  5. }  

二、关联关系
        1.说明:
        实线+箭头 可以描述为has a
        关联关系用实线,表示类之间的耦合度比依赖强。在生成代码的时候,关联关系的类会增加属性
        2.关联关系和代码的对应关系
                

  1. Public class Water {  
  2.      public Climate m_Climate;  
  3.      public Water(){}  
  4. }  
  5.    
  6. Public class Climate {  
  7.      public Climate() {}  
  8. }  

        可见,生成的代码中,water类的属性中增加了Climate类
        3.关联的种类
        关联有单向关联和双向关联
        单向关联:water类和Climate类单向关联,则water类称为源类,Climate类称为目标类。源类了解目标类的所有属性和方法,但目标类并不了解类的信息
        
        双向关联:源类和目标类互相了解彼此的信息,如将water类和Climate类之间改为双向关联
                

  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() {}  

        可见,生成的代码中,两个类的属性都添加了
        4.思考:
        依赖关联和关联关系的区别在哪里?
        (1)从类的属性是否增加的角度看:
            发生依赖关系的两个类都不会增加属性,其中的一个类作为另一个类的方法的参数或者返回值,或者是某个方法的变量而已。
            发生关联关系的两个类,其中的一个类称为另一个类的属性,而属性是一种更为紧密的耦合,更为长久的持有关系。
        (2)从关系的生命周期角度看:
            依赖关系是仅当类的方法被调用时而产生的,伴随着方法的结束而结束了。
            关联关系是当类实例化的时候即产生,当类销毁的时候,关系结束。相对依赖来说,关联关系的生存周期更长
        5.关联关系的细化:聚合和组合
        (1)聚合:用空心菱形+箭头
                组合:用实心菱形+箭头,类之间的耦合比聚合强
        (2)聚合和组合生成的代码
                    
            (PS:此图表明雁群类是由大雁类聚合而成)

  1. Public class GooseGroup {  
  2.     public Goose goose;  
  3.     Public GooseGroup(Goose goose) {  
  4.               this.goose = goose;  
  5.        }  
  6. }  

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

  1. Public class Goose {  
  2.    public Wings wings;  
  3.    public Goose() {  
  4.        wings = new Wings();  
  5.     }  
  6. }  

        (3)构造函数不同
             聚合类的构造函数中包含了另外一个类作为参数,GooseGroup的构造函数中用到Goose作为参数传递进来,Goose可以脱离GooseGroup独立存在
            组合类的构造函数中包含了一个类的实例化,表明大雁类在实例化之前,一定要先实例化Wings类,这两个类紧密的耦合在一起,同生共灭。wings类是不可以脱离大雁类独立存在的
       (4)信息的封装性不同
            聚合关系中,客户端可以同时了解GooseGroup和大雁类,因为他们是独立的
            在组合关系中,客户端只认识大雁类,根本就不知道wings类的存在,因为wings类被封装在Goose类中
三、泛化
    1.说明:
        实线+箭头 可描述为is a
        泛化也成继承,子类将继承父类的所有属性和方法,并且可以根据需要对父类进行扩展
    2.泛化关系与代码的对应关系
        
        PS:Bird类继承了animal类

  1. Class  Bird :Animal{  
  2. }  

    3.思考:
        (1)子类继承父类,真的是继承了父类的所有属性和方法吗?
            子类确实继承了父类的所有属性和方法,只是对于父类的私有类型成员没有访问权限
        (2)泛化和继承是一回事吗?
            子类继承父类,父类泛化子类,不同角度来解释而已
        (3)为什么药多用组合少用继承?
            组合和继承各有优缺点。
            类继承是在编译时刻静态定义的,且可直接使用,类继承可以较方便的改变父类的实现,但是类继承也有一些不之处。首先,因为继承在编译时刻就定义了,所以无法再运行时刻改变父类继承的实现。更糟的是,父类通常至少定义了子类的部分行为,父类的任何改变都可以影响子类的行为,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的替换。这种依赖关系限制了灵活性并最终限制了复用性。
            组合是通过获取对其他对象的引用而在运行时刻动态定义的,由于组合要求具有良好定义的接口,而且,对象只能通过接口访问,所以我们并不破坏封装性;只要类型一致,运行时刻还可以用一个对象来替代另一个对象;更进一步,因为对象的实现是基于接口写的,所以实现上存在较少的依赖关系。
四、实现
    1.说明:
        虚线+箭头
        
        PS:Win的Goose类实现IFly接口

  1. Class WideGoose:Ifly{   
  2. }

    2.接口的定义:
        是一种特殊的抽象类,这种抽象类中值包含常量和方法的定义,而没有变量和方法的实现

赞(0)
【声明】:本博客不参与任何交易,也非中介,仅记录个人感兴趣的主机测评结果和优惠活动,内容均不作直接、间接、法定、约定的保证。访问本博客请务必遵守有关互联网的相关法律、规定与规则。一旦您访问本博客,即表示您已经知晓并接受了此声明通告。