• UML系列 (三) 四种关系


            1、继承是面向对象编程一大特点,如果两个对象A和B,可以描述为“B是A”,则表明B可以继承A。继承者还可以理解为是对被继承者的特殊化,因为它除了继承者的特性外,还具备自己独有的特性;继承一般可说成父类和子类或基类和派生类。如下面例子:

    a  为了使子类的实例完全接替来自父类的成员,父类必须将该成员声明为虚拟的。在返回类型之前加上关键字“virtual”。

    b  子类可以选择使用关键字“override”,将父类实现替换为它自己的实现。

    c  这样方法重写,其实,是实现了“多态”。

    d  多态是指不同的对象可以执行相同的动作,但要通过它们自己的实现代码来执行。




             继承的优点是使得代码到了共享,避免了重复,增加了功能的可扩展性,而缺点为父类变,则子类就变,父类实现细节暴露给子类,增强了类与类之间的耦合性。

            2、依赖是一种类与类之间弱耦合的关系,如下图用虚线箭头表示:


           在五种关系中,依赖是耦合最小的一种,在类与类的代码中都不会增加属性,如下图:


    a 在Animal类中,没有Water属性,那么Animal类怎么使用Water类呢?有三种方式

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

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

    Water类的生命期,它是当Animal类的方法被调用的时候,才被实例化。
    持有Water类的是Animal的一个方法而不是Animal

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

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

           3 关联用实线箭头表示,如下图:


     如下代码:在类cloud属性中,添加了Climate


       关联既有单向关联又有双向关联,上图中为单向关联,Cloud类成为源类,Climate类成为目标类,源类了解目标类的属性、成员、信息,但目标类不了解源类。

       双向关联,有双向箭头,信息相互了解。

        在各自代码中,都有对方类,作为自己的一个属性成员。

    依赖和关联的区别:

    a 从类的属性是否增加的角度看:

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

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

    从关系的生命期角度看:

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

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

    l 聚合和组合的区别:

         我们大家都知道表面上他们的区别,聚合比组合关系弱一些,那么这个弱的关系如何在代码中体现呢?

    区分的关键有两点:



    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    下面为,大话设计中一个例子:两个类之间为聚合关系。

        //工作经历类
        class WorkExperience
        {
            private string workDate;
            public string WorkDate
            {
                get { return workDate; }
                set { workDate = value; }
            }
            private string company;
            public string Company
            {
                get { return company; }
                set { company = value; }
            }
        }
        //简历代码
        class Resume:ICloneable
        {
            private string name;
            private string sex;
            private string age;
            //引用工作经历对象
            private WorkExperience work;
    
            public Resume(string name)
            {
                this.name = name;
                //在“简历”类实例化时,同时实例化,“工作经历类”
                work = new WorkExperience();
            }
            //设置个人信息
            public void SetPersonInfo(string sex, string age)
            {
                this.sex=sex;
                this.age=age;
            }
            //设置工作经历
            public void SetWorkExperience(string workDate,string company )
            {
                //在调用此方法时,给对象的两个属性赋值
                work.WorkDate = workDate;
                work.Company = company;
    
            }
            public void Display()
            {
                Console.WriteLine("{0}{1}{2}",name,sex,age);
                //显示时,显示“工作经历”的两个属性值
                Console.WriteLine("工作经历:{0}{1}",work.WorkDate,work.Company);
            }
            public object Clone()
            {
                return (object)this.MemberwiseClone();
            }
    
        }


    这两种关系的区别在于:

    ①构造函数不同

    聚合类的构造函数中包含了另一个类作为参数。

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

    组合类的构造函数中包含了另一个类的实例化。

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

    信息的封装性不同

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

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


    在这里涉及到一个设计模式即CARP模式,合成、聚合复用原则,尽量使用合成、聚合,尽量不用使用类继承。继承是一种强耦合关系,父类变,子类就必须变。


         


  • 相关阅读:
    我的VIM.rc
    汉字编码
    儿童绘本
    禁用Linux bash rm --force
    English Audio-Books
    谱曲软件-MuseScore
    redis cluster 的ERR max number of clients reached 问题排查
    mycat引起的insert后马上select不到数据的故障分析
    生产环境elasticsearch
    docker kafka 修改hostname导致的问题
  • 原文地址:https://www.cnblogs.com/lilongsheng/p/3226132.html
Copyright © 2020-2023  润新知