UML(Unified Modeling Language)是统一建模语言,1997年11月UML1.1版本提交给OMG并正式经过,成为建模语言的个那个也标准。2003年6月UML2.0得到正式经过。编程
UML结构一般包括如下4个部分:视图,图,模型元素以及通用机制。设计模式
UML视图用于从不一样的角度来表示待建模的系统。视图是由许多图形组成的一个抽象集合,在创建一个系统模型时,只有经过定义多个视图,每一个视图显示该系统的一个特定方面,才能构造出该系统的完整蓝图。bash
UML视图包括:微信
UML图是描述UML视图内容的图形,UML2.0提供了13种图,分别是用例图,类图,对象图,包图,组合结构图,状态图,活动图,顺序图,通讯图,定时图,交互概览图,组件图和部署图。其中:编程语言
模型元素是指UML图中所使用的一些概念,对应于普通的面向对象概念,如类,对象,消息以及这些概念之间的关系,如关联关系,泛化关系等。ide
UML提供的通用机制为模型元素提供额外的注释,信息和语义,这些通用机制也提供了扩展机制,容许用户对UML进行扩展,如定义新的建模元素,扩展原有的语义,添加新的特殊信息来扩展模型元素的规则说明等,以便适用于特定的方法或过程,组织和用户。函数
类封装了数据和行为,是具备相同属性,操做,关系的对象集合的总称。类图是用出如今系统中不一样类来描述系统的静态结构,主要描述不一样的类以及它们之间的关系。工具
在UML中,类图包含类名,属性以及操做。以下面的Employee类:开发工具
类通常由三部分组成:this
类名就是类的名字,一个字符串。
类的成员变量,通常的格式为
可见性 名称 : 类型 [ = 默认值]
可见性表示该属性对于类外的元素是否可见,包括:
+
-
#
~
UML规定操做的定义方式为:
可见性 名称(参数列表)[ : 返回类型]
,
分隔UML提供了四种不一样的方式表示类与类之间的关系:
下面逐个看一下。
关联关系是一种结构化关系,用于表示一类对象与另外一类对象之间有联系。在UML中用实线链接有关联关系的类。能够在关联线上标注角色名,关系的两端表明两种不一样的角色,所以在一个关联关系中能够包含两个角色名,角色名不是必须的,但可使类之间的关系更加明确。
例如在一个登陆界面类LoginForm
包含一个JButton
:
UML中关联一般包括如下六种形式:
默认状况下关联是双向的,例如顾客购买商品并拥有商品,反之卖出的商品老是某个顾客与之相关联:
关联也能够是单向的,在UML中关联用带箭头的实线表示,好比顾客拥有地址:
系统中可能会存在一些类的属性对象类型为该类自己,这种特殊的关联关系为自关联,常见于链表:
多重性关联又称为多重性关联联系,表示两个关联对象在数量上的对应关系。在UML中,对象之间的多重性能够直接在关联直线上用一个数字或者一个数字范围来表示。常见的表示方式以下:
例如一个界面能够具备0个或多个按钮,可是一个按钮只能从属于一个界面:
聚合关系表示总体与部分的关系,使用空心菱形表示。聚合关系中部分是总体的一部分,可是部分能够脱离总体独立存在,好比引擎是汽车的一部分,可是引擎能够独立于汽车存在:
组合关系也表示总体与部分之间的关系,可是部分不能脱离总体存在。组合关系使用实心菱形表示。好比人的头和嘴巴是组合关系:
依赖关系是一种使用关系,在须要表示“一个事物使用另外一个事物”时使用依赖关系。UML中依赖关系用带箭头的虚线表示,由依赖的一方指向被依赖的一方。例如驾驶员开车,开车须要车,也就是驾驶员依赖于车:
泛化关系也就是继承关系,用于描述父类与之类之间的关系,父类又叫基类或者超类,子类又称做派生类。UML中泛化关系用带空心三角形的直线表示,箭头指向基类:
不少语言好比Java,C#都有接口的概念,接口一般没有属性,全部是操做都是抽象的,只有操做的声明没有操做的实现。UML中使用<<Interface>>
表示接口:
类与接口之间的实现关系使用空心三角形+虚线表示:
面向对象设计的目标之一是支持可维护性复用,一方面须要实现设计方案或者源代码的重用,一方面要确保系统可以易于扩展和修改,具备较好的灵活性。面向对象设计原则由此诞生,它们蕴含于不少设计模式中,是从许多方案总结出来的指导性原则。常见的7种面向对象设计原则以下:
单一权责原则(Single Responsibility Principal):一个类只负责一个功能领域中的相应职责。
或者能够定义为:就一个类而言,应该只有一个引发它变化的缘由。
单一权责原则的核心思想是:一个类不能太“累”。一个类(大到模块,小到方法)承担的职责越多,被复用的可能性越小,并且一个类承担的职责过多,就至关于将这些职责耦合在一块儿,当其中一个职责变化时,可能会影响其余职责的运做,所以须要将职责分离,封装在不一样的类中,即将不一样的变化缘由封装在不一样的类中。单一权责原则是实现高内聚,低耦合的指导方针。
开闭原则(Open-Closed Principle):一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽可能不修改原有代码的状况下进行扩展。
其中软件实体能够是一个软件模块,一个由多个类组成的局部结构或者一个独立的类。
一个软件设计符合开闭原则,则能够很是方便地对其进行扩展,并且在扩展时无须修改现有代码,使得软件系统在拥有适应性和灵活性的同时具有较好的稳定性和延续性。
为了知足开闭原则,须要对系统进行抽象化设计,抽象化是开闭原则的关键。能够经过接口,抽象类等定义抽象层,经过具体类进行扩展,修改系统的行为时无需修改抽象层,只须要增长新的具体类来实现新的业务功能便可,实如今不修改已有代码的基础上扩展系统的功能,达到开闭原则的要求。
里氏代换原则(Liskov Substitution Principle):全部引用基类/父类的地方必须能透明地使用其子类的对象。
简单地说就是父类出现的地方能够用子类代替,程序不会产生任何的错误和异常。使用里氏代换原则时,应该将父类设计为抽象类或者接口,让子类继承父类或实现父类接口,并实现父类中声明的方法,运行时,子类实例代替父类实例,能够很方便地扩展系统的功能,无须修改原有子类的代码,增长新的功能能够经过增长一个新的子类来实现。
依赖倒转原则(Dependency Inversion Principal):抽象不该该依赖具体细节,细节应当依赖于抽象,换言之要针对接口编程,而不是针对实现编程。
依赖倒转原则要求程序在源代码中传递参数时或者在关联关系中,尽可能引用高层次的抽象层类,即便有接口和抽象类进行变量类型声明,参数类型声明,方法返回类型声明以及数据类型的转换等,而不是用具体类来作。一个具体类应该只实现接口或者抽象类中声明过的方法,而不要给出多余的方法,不然将没法调用在子类中新增的方法。
在实现依赖倒转原则时,须要针对抽象层进行编程,而将具体类的对象经过依赖注入(Dependency Injection)的方式注入到其余对象中。依赖注入是指当一个对象要与其余对象发生依赖关系时,经过抽象来注入所依赖的对象。经常使用的注入方式包括:
上面的方法在定义时使用抽象类型,在运行时传入具体类型的对象,由子类对象来覆盖父类对象 。
接口隔离原则(Interface Segregation Principal):使用多个专门的接口,而不使用单一的总接口,即客户端不该该依赖于那些它不须要的接口。
也就是说,当一个接口太大时须要划分为更小的接口,使用该接口的客户端仅需知道与之相关的方法。每个接口应该承担一种相对独立的角色,这里的接口有两层意思:
ISP对两种不一样含义的表达方式有所不一样:
使用接口隔离原则时,注意控制接口的粒度:
通常而言接口中仅包含为某一类用户定制的方法便可。
合成复用原则(Composite Reuse Principal):尽可能使用对象组合而不是继承来达成复用目的。
合成复用原则又叫组合/聚合复用原则(Composition/Aggregate Reuse Principal),就是在一个新对象中经过关联关系(组合/聚合)对对象进行重用而不是使用继承。
面向对象设计中,能够经过两种方法在不一样环境中复用已有的设计和实现:
继承须要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,下降复杂度,而滥用继承反而会增长系统构建和维护的难度以及系统的复杂度。继承主要带来的问题是会破环系统的封装性,由于继承会将基类实现细节暴露给子类,因为基类内部细节对子类可见,所以叫“白箱复用”。
通常而言两个类之间的关系是“Is-A”关系就可使用继承。
尽管能够经过继承来对代码进行复用,通常来讲优先考虑组合/聚合。组合/聚合可使系统更加灵活,下降类与类之间的耦合度。因为新对象能够直接调用已有对象的功能,这样作可使成员对象的内部实现细节对新对象不可见,因此这种复用叫“黑箱复用”。
通常而言两个类之间的关系是“Has-A”关系就可使用组合/聚合。
迪米特法则(Law of Demeter):一个软件实体应当尽量少地与其余实体发生相互做用。
迪米特法则又叫最少知识原则(Least Knowledge Principal,LKP),迪米特法则会对软件实体之间通讯的宽度与深度进行限制,能够下降系统的耦合度,使类与类之间保持松耦合。
迪米特法则还有几种定义形式:不要和“陌生人”说话,只与直接朋友通讯。对于一个对象“朋友”能够是如下几类:
知足上述条件之一便是“朋友”,不然就是“陌生人”,不能和“陌生人”发生直接交互。
迪米特法则要求设计系统时尽可能减小对象之间的交互,经过引入一个合理的中间类来下降现有对象之间的耦合度。应用迪米特法则时须要注意几点:
若是以为文章好看,欢迎点赞。
同时欢迎关注微信公众号:氷泠之路。