《小酌重构系列》已经完成了大约1/3了,在这些文章中,我使用了一些简单的类图来描述重构策略。在以后的文章中,我可能会借助稍微复杂一些的UML类图来介绍。可是在此以前,我以为有必要先介绍一下UML类图中6大关系了。这6大关系分别是Inheritance(继承)、Implementation(实现)、Dependency(依赖)、Association(关联)、Aggretation(聚合)和Composition(组合)。在这6大关系中,依赖、关联、聚合和组合是比较容易混淆的,我也会讲解它们之间的区别。java
UML是Unified Modeling Language的缩写,翻译为中文是“统一建模语言”,它是面向对象软件的标准化建模语言。它是一个支持模型化和软件系统开发的图形化语言,为软件开发的全部阶段提供模型化和可视化支持,包括由需求分析到规格,到构造和配置。工具
不一样组织不一样软件对UML的种类划分是不一样的,基本全部的UML的软件都包含了如下4大种类spa
UML类图用于展示了一组对象、接口、协做和它们之间的关系。类图描述的是一种静态关系,在系统的整个生命周期都是有效的,是面向对象系统的建模中最多见的图。翻译
市面上UML的工具软件很是多,每一个人的口味不一样,我就很少作介绍了,我最经常使用的UML工具是Visio。设计
固然做为一个.NET开发者,Ultimate版本的Visual Studio也提供了UML建模功能。3d
Inheritance表示一个类(接口)继承另外一个类(接口)的功能和属性,用于描述父类(接口)和子类(接口)之间的关系。
继承描述了"is a kind of "关系,例如:Manger是Employee的一种,Manager继承了Employee的全部功能(例如:刷卡签到、执行工做)和属性(例如:员工姓名、入职时间)。对象
在UML中,继承使用实线空心箭头表示,空心箭头指向父类(接口)。blog
Implementation表示类实现接口的功能。继承
在UML中,继承使用虚线空心箭头表示,空心箭头指向接口。接口
虽然在C#中继承和实现都使用符号:来表示(java中使用extends表示继承,implements表示实现),但两者仍是有些区别的。
1. 继承发生在“类和类”或“接口和接口”之间,例如:子类继承父类,子接口继承父接口。
子类继承父类:
public abstract class Animal { } public class Bird : Animal { }
子接口继承父接口:
public interface ITransportation { void Move(); } public interface IVehicle : ITransportation { }
2. 实现发生在“类和接口”之间,例如:类实现某个接口的方法。
public interface IVehicle : ITransportation { } public class Car : IVehicle { public void Move() { Console.WriteLine("汽车跑起来..."); } }
3. 在C#中,多继承确切地说是多实现。
不像C++语言的语法,C#的类不能同时继承多个类。C#仅能继承一个类,但能够同时实现多个接口。
例如:ASP.NET MVC中的Controller类,继承了ControllerBase类,同时实现了IActionFilter, IAuthenticationFilter…等接口。
public abstract class Controller : ControllerBase, IActionFilter, IAuthenticationFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter, IAsyncController, IAsyncManagerContainer { }
在UML中,依赖关系使用虚线箭头表示,箭头指向被依赖的一方。
例如:在Web Service中,Client须要调用Service的操做,这就表示Client依赖于Service。
在UML中,关联关系使用一条直线表示。
例如:Student和Teacher之间就属于”Association”,多个Student能够关联到一个Teacher,一个Student也能够关联到多个Teacher。
可是Teacher和Student之间没有“从属”或“包含”关系。
在UML中,聚合关系使用空心菱形箭头表示,箭头指向总体。
例如:一个Department拥有多个Employee,Department做为总体,Department中的Employee是Department的一部分。
Department和Employee都有本身的生命周期,当一个Department被撤销时,Employee能够转到其余Department或离职了。
Employee转到其余Department或离职时,Department仍然是存在的。
在UML中,组合关系使用实心菱形箭头表示,箭头指向总体。
例如:一套房屋有多个房间,房间是房屋的一部分。房间的生命周期依赖于房屋的生命周期,当房屋被拆掉时,房间也就不存在了。
依赖、关联、聚合和组合均可以泛指为”依赖关系”。
当对象之间构成Association、Aggregation或Composition关系时,也创建了对象之间的依赖关系。
它们表现的依赖关系强弱程度不一样,这4种关系所表现的强弱程度依次为:Composite > Aggregation > Association > Dependency。
关联、聚合和组合是你们常常容易混淆的3种关系,这种关系最大的区别在于对象的生命周期。
今天有读者问到了一个问题:分清楚这些符号有必要吗?
个人回答是:因团队而异,这取决于团队沟通和交流的方式,也取决于团队成员的能力。
UML是一种沟通语言,你能够经过它模糊地表达一段内容,你也能够准确地描述这些内容,只要团队的其余成员可以领会你的意思。
沟通是以结果为向导的,你大可没必要拘泥于沟通的方式,但在沟经过程中准确有效地表达尤为重要,这里的“准确”不是指准确地使用UML符号,而是指他人能准确地领会你所表达的内容。
我我的以为:在涉及到系统中关键的模型时,用确切的符号来表达关系仍然是比较重要的。
例如:在一个采购系统中,拥有采购申请 → 采购订单这样一个流程。采购申请由用户选择商品、供应商后建立;采购订单由审核过的采购申请生成。
这里存在3对关系:
1. 采购申请和采购申请明细的关系
2. 采购订单和采购订单明细关系
3. 采购申请和采购订单之间的关系
从业务上看,一、2是一种组合关系,3是一种关联关系。若是笼统地将一、二、3理解为依赖关系,可能会产生一些问题。
在设计过程当中,若是咱们正确地描述了这3对关系,那么在删除单据时,可根据确切的关系概括出如下行为:
1. 删除采购申请时,采购申请明同时被删除(由于它们是组合关系)
2. 删除采购订单时,采购订单明细同时被删除(由于它们是组合关系)
3. 删除采购订单时,不影响采购申请(由于它们是关联关系)