在起初学习UML的时候并没有深入了解的太多,但是最近在研究机房重构UML的九种图时就有许多的困惑。尤其是在验收的时候,为什么必须有图呢??没有图又会有什么影响呢?一时间有点摸不到头脑。
这几天经过查询一些资料,发现UML图非常的神奇。尤其是UML图中的类图。可以说功能非常的强大了。类图中常见的有六种关系:泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation),组合(Composition),依赖(Dependency)。这几种关系通过查询发现其中的奥秘之深:每一种关系都有其对应的代码格式。今天就简单总结一下。
UML的记忆
首先查询到一个记忆几种关系的口诀,可以说是非常棒的:【是不是念一遍就记住了这六种关系呢?】
凡(泛化)是(实现)狙(聚合)击组(组合),都可以(依赖)来参观(关联)
UML关系
关于代码的实现方面,首先需要知道这些关系描述的是类和类之间,还是类与接口,还是接口与接口等等之间的关系
关系 | 耦合度 | 举例 | 说明 |
依赖 |
最小 | Animal------>Water Phone------->Charger |
虚线+箭头(User a) |
关联 | 较小 | Student——>University |
双向的关联可以有两个箭头或者没有箭头,单向的关联有一个箭头(has a ) |
聚合 | 适中 | GooseGroupGoose |
用空心菱形加箭头表示,菱形指向整体 |
组合 | 较大 | GooseWings | 用实心菱形加箭头表示,菱形指向整体 |
继承(泛化) | 大 | BirdAnimals | 实心+空心三角(Is a ) |
实现 | 大(类实现接口) | WideGooseIFly | 虚线+三角 |
UML关系的实现
几种关系的描述说完了,那放在C#代码中又是怎么实现的呢?
博客的参照:https://blog.csdn.net/lfsf802/article/details/8987267
一、依赖
依赖是几种关系中耦合度最小的,在生成代码的时候,两个关系类不会增加属性、
(动物依赖于水)
Public class Animal()
{
Public Animal(){}
}
Public class Water()
{
public Water(){}
}
那么如何在代码中体现出来依赖呢?
第一种表现:
Water是全局变量。那么Animal可以调用Water。
第二种表现:
Water类是作为Animal类中某个方法的参数或者返回值 (如下调用),这像七层中实体的传递。
Public class Animal
{
Public void Grownup( Water water) { }
}
注意: Water类被Animal类的一个方法持有。生命期随着方法的执行结束而结束。
第三种表现:
Water类是 Animal类的某个方法中的变量,则Animal类可以调用它。
Public class Animal
{
Public void Grownup()
{
Water water =null;
}
}
注意1: Water类的生命期,它是当Animal类的GrounUp方法被调用的时候,才被实例化。
注意2:持有Water类的是Animal的一个方法而不是Animal类,这点是最重要的!
二、关联
当一个类需要知道另一个类时需要用到关联关系,关联关系用实线箭头表示。
1)单向关联
class Penguin:Brid
{
private Climate climate;//在企鹅Penguin中,引用到气候Climate对象
}
2)双向关联:源类和目标类相互了解彼此的信息。如将Water类和Climate类之间双向关联。
关联和依赖的区别:
1、从类的属性是否增加的角度看
(1)发生依赖关系的两个类都不会增加属性。其中的一个类作为另一个类的方法的参数或者返回值,或者是某个方法的变量而已。
(2)发生关联关系的两个类,其中的一个类成为另一个类的属性,而属性是一种更为紧密的耦合,更为长久的持有关系。
2、从关系的生命期角度看:
(1)依赖关系是仅当类的方法被调用时而产生,伴随着方法的结束而结束了。
(2)关联关系是当类实例化的时候即产生,当类销毁的时候,关系结束。相比依赖讲,关联关系的生存期更长。
3.调用关系
(1)依赖关系
依赖关系表示的是类之间的调用关系,即用一个类去调用另外一个类,
被调用的类表现为调用类的 局部变量,方法的参数,调用类调用被调用类的静态方法。
(2)关联关系
表示两个类之间的联系,通过这种联系,一个类可以访问到另外一个类的属性和方法。
这两个类是互相独立的,这两个类可以单独存在。
三、聚合和组合
最常见的事雁群和大雁的关系。大雁可以脱离雁群单独存在,这是聚合
大雁由翅膀,喙,羽毛等组成,这体现的式组合,不能脱离
(此为聚合)
表示一种弱“拥有”关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分。
Public classGooseGroup
{
public Goose goose;
Public GooseGroup(Goose goose)
{
this.goose = goose;
}
}
(此为组合)
是一种强的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的声明周期一样
Public classGoose
{
public Wings wings;
public Goose()
{
wings = new Wings();
}
}
四、继承(泛化)
泛化也称为继承,子类将继承父类所有的属性和方法,并且可以根据需要对父类进行拓展。
以下为继承关系:
Class Bird :Animal{}
注意:
1、子类继承的是父类公共的和Proctected属性和方法,私有的属性和方法是不能继承的。子类除了可以继承父类的属性和方法,还可以扩展父类没有的属性和方法。。子类以自己的方式实现父类的功能:重写。
2、 子类继承父类,父类泛化子类。 这两个词是从不同的角度来说的!
优缺点:
优点:继承是所有的子类公共的部分都放在了父类,使得代码得到了共享,避免了重复,是修改和扩展继承而来的实现都较为容易。
缺点:父类变子类不得不变。继承会破坏包装,父类实现细节暴露给子类,使得耦合性增强。
五、实现
实现:一般涉及到接口,
Class WideGoose:Ifly{}
接口(interface),接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。