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模式,合成、聚合复用原则,尽量使用合成、聚合,尽量不用使用类继承。继承是一种强耦合关系,父类变,子类就必须变。


     


posted @ 2012-01-09 16:00  李龙生的博客  阅读(155)  评论(0编辑  收藏  举报