从UML类图关系到依赖注入(IoC)


本篇文章源于该篇文章《UML类图很难吗?这样理解一文就通》。因为小马以此为基础整理了一次内部分享会,所以讲内容展开具体化了,也可以认为是上一篇文章的升级版。

该标题为什么如此奇葩而不失优雅呢?因为本来小马是打算直奔主题,直接分享IoC的,但又考虑如果对依赖注入不熟悉就不好理解,如果对类的关系不理解又不好理解依赖注入,如果要理解类的关系就必须引入类图关系来介绍,如果引入类图的话就不得不从UML说起,于是就诞生了这个奇怪的标题。

小马把本次的内容调侃为:适用场景:软考考试敲黑板必考题,架构师一技能,码猿代码实现与编写框架思想神器,面试护盾...

后面加了一堆省略号一点也不为过,哈哈哈。

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来降低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入。

目录

1.UML

2.UML类图关系

3.依赖强弱

4.依赖注入

5.Ioc

一、UML

UML统一建模语言

要从UML说起,虽然并不是本次的重点内容。

百科怎么说?

Unified Modeling Language 统一建模语言,又称标准建模语言。是用来对软件密集系统进行可视化建模的一种语言。UML的定义包括UML语义和UML表示法两个元素。

UML是在开发阶段,说明、可视化、构建和书写一个面向对象软件密集系统的制品的开放方法。最佳的应用是工程实践,对大规模,复杂系统进行建模方面,特别是在软件架构层次,已经被验证有效。统一建模语言(UML)是一种模型化语言。模型大多以图表的方式表现出来。一份典型的建模图表通常包含几个块或框,连接线和作为模型附加信息之用的文本。这些虽简单却非常重要,在UML规则中相互联系和扩展。


UML的作用

概括起来说,UML主要有以下作用:

(1)为软件系统建立可视化模型。

UML符号具有良好的语义,不会引起歧义;基于UML的可视化模型,使系统结构直观、易于理解;使用UML进行软件系统的模型不但有利于系统开发人员和系统用户的交流,还有利于系统维护。模型是系统的蓝图,它可以对开发人员的规划进行补充,模型可以帮助开发人员规划要建的系统。有了正确的模型就可以实现正确的系统设计,保证用户的要求得到满足,系统能在需求改变时站得住脚。对于一个软件系统,模型就是开发人员为系统设计的一组视图。这组视图不仅描述了用户需要的功能,还描述了怎样去实现这些功能。

(2)为软件系统建立构件。

UML不是面向对象的编程语言,但它的模型可以直接对应到各种各样的编程语言。例如,它可以使用代码生成器工具将UML模型转换为多种程序设计语言代码,如可生成C++,XML,DTD,JAVA, Visual basic等语言的代码,或使用反向生成器工具将程序源代码转换为UML;甚至还可以生成关系数据库中的表。

(3)为软件系统建立文档。

UML可以为系统的体系结构及其所有细节建立文档。不同的UML模型图可以作为项目不同阶段的软件开发文档。

UML特点

(1)UML统一了各种方法对不同类型的系统、不同开发阶段以及不同内部概念的不同观点,从而有效的消除了各种建模语言之间不必要的差异。它实际上是一种通用的建模语言,可以为许多面向对象建模方法的用户广泛使用。

(2)UML建模能力比其它面向对象建模方法更强。它不仅适合于一般系统的开发,而且对并行、分布式系统的建模尤为适宜。

(3)UML是一种建模语言,而不是一个开发过程。

UML图的种类

2.0版本之后增加到13种

UML各种图的作用

用例图:从用户角度描述系统功能。

类图:描述系统中类的静态结构。

对象图:系统中的多个对象在某一时刻的状态。

状态图:是描述状态到状态控制流,常用于动态特性建模

活动图:描述了业务实现用例的工作流程

顺序图:对象之间的动态合作关系,强调对象发送消息的顺序,同时显示对象之间的交互

协作图:描述对象之间的协助关系

构件图:一种特殊的UML图来描述系统的静态实现视图

部署图:定义系统中软硬件的物理体系结构

包图:对构成系统的模型元素进行分组整理的图

组合结构图:表示类或者构建内部结构的图

交互概览图:用活动图来表示多个交互之间的控制关系的图

然而,我们今天并不关心各种图的作用,有兴趣的小伙伴可以自行研究,参考《九种模型图的参考示例》, 我们今天只关心类图。

二、UML类图关系

类图:

在UML的静态机制中类图是一个重点,它不但是设计人员关心的核心,更是实现人员关注的核心。建模工具也主要根据类图来产生代码。类图在UML的9个图中占据了一个相当重要的地位。James Rumbaugh对类的定义是:类是具有相似结构、行为和关系的一组对象的描述符。类是面向对象系统中最重要的构造块。类图显示了一组类、接口、协作以及他们之间的关系。在UML中问题域最终要被逐步转化,通过类来建模,通过编程语言构建这些类从而实现系统。类加上他们之间的关系就构成了类图,类图中还可以包含接口、包等元素,也可以包括对象、链等实例。

类之间的关系:

常见的有以下几种关系:泛化(Generalization), 实现(Realization),组合(Composition),聚合(Aggregation),关联(Association),依赖(Dependency)。

下图中,类图之间分别是什么关系呢?

根据图我们可以自己总结一些口令便于记忆(因为考试总会考这些):箭头指向于依赖于;根据依赖强弱,图标分别是箭头,箭尾,方向标。--这些如何理解下文会讲到。

泛化(Generalization)

【泛化关系】:是一种继承关系,它指定了子类如何特化父类的所有特征和行为例如:老虎是动物的一种.

【代码体现】:继承

【箭头指向】:带三角箭头的实线,箭头指向父类

实现(Realization)

【实现关系】:是一种类与接口的关系,表示类是接口所有特征和行为的实现

【代码体现】:接口实现

【箭头指向】:带三角箭头的虚线,箭头指向接口

组合(Composition)

【组合关系】:是整体与部分的关系。组合关系是关联关系的一种,是比聚合关系还要强的关系,它要求普通的聚合关系中代表整体的对象负责代表部分的对象的生命周期(同时消亡)。比如没有公司就不存在部门。

【代码体现】:成员变量

【箭头及指向】:带实心菱形的实线,菱形指向整体(有些是右边也有箭头)

注意有些右边是带箭头的

聚合(Aggregation)

【聚合关系】:是整体与部分的关系。如汽车类和轮胎类是整体和部分的关系。整件不会拥有部件的生命周期,所以整件删除时,部件不会被删除。

聚合关系是关联关系的一种,是强的关联关系;关联和聚合在语法上无法区分,必须考察具体的逻辑关系。

【代码体现】:成员变量

【箭头及指向】:带空心菱形的实心线,菱形指向整体

注意有些右边是带箭头的

关联(Association)

【关联关系】:是一种拥有的关系,它使一个类知道另一个类的属性和方法;如:老师与学生,丈夫与妻子,我和我的朋友。

关联的两个对象之间一般是平等的,而在聚合关系中,两个类是处在不平等层次上的,一个代表整体,另一个代表部分。

关联可以是双向的,也可以是单向的(可以自己关联自己)。双向的关联可以有两个箭头或者没有箭头,单向的关联有一个箭头。

【代码体现】:成员变量

【箭头及指向】:带普通箭头的实心线,指向被拥有者

注意双向关联有些左右是带箭头的

依赖(Dependency)

【依赖关系】:是一种使用的关系,所以要尽量不使用双向的互相依赖。比如动物新陈代谢需要氧气、水。

【代码表现】:局部变量、方法的参数或者对静态方法的调用

【箭头及指向】:带箭头的虚线,指向被使用者


三、依赖强弱

关联关系的强弱:

有时候,我们也把组合、聚合、关联、依赖都叫做“依赖”或者笼统地归结为关联关系,可以认为是关联关系的一种强弱表达。后面我们会讲到依赖注入。

关系的强弱顺序或者说耦合度强弱:

泛化= 实现> 组合> 聚合> 关联> 依赖

思考:如果给出一段代码实现如何区分类之间是什么关系,尤其是组合、聚合、关联?

依赖比较好区分,因为其表现为局部变量、方法的参数或者对静态方法的调用;

而聚合、组合、关联都是成员变量注入只能配合语义,结合上下文才能够判断出来,而只给出一段代码让我们判断是关联,聚合,还是组合关系,则是无法判断的,上面说到其代码实现都是成员变量/类属性。

四、依赖注入

依赖关系代码

思考:上面代码中体现了哪些“依赖”关系?有没存在什么问题?

语义上:老师与学生 =》 关联关系

实现上:严格意义上来说不能算依赖注入(依赖倒转),算依赖实现

teacher1类与student类  成员变量注入=》关联关系    =》组合,聚合,关联都是用成员变量注入

teacher2类与student类  command1方法形参;command2 局部变量 ;  command3 对静态方法的调用    注入  =》依赖关系 =》如果区分语义,学生和老师的关联关系不能按依赖关系来实现

通俗地理解为依赖就是我自己不能单独完成任务,必须要引入外部别人的资源来一起完成任务。

依赖注入

如上,假如这个时候老师想换教学对象了,教老年人。那么需要更改自己的代码new student()为new elder();假如又突然被调配成教中年人呢?是不是要一直改代码。这其实是一个强耦合。下面代码我们进行了形参依赖注入,还有一种是构造器注入。

对于依赖注入而言,需要遵循依赖倒转原则。

依赖倒转原则:

依赖倒转原则(Dependence Inversion Principle)是程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。

依赖注入的好处:

依赖之间的解耦

单元测试,方便Mock

五、IoC

依赖注入它不香吗?为啥还要引入IoC容器?

大多数时侯,在使用依赖注入方式解耦组件时,并不需要用到容器。当一段程序需要实例化的类太多或者依赖太多的时候,重复依赖注入的代码是比较繁琐的事情,此时需要使用容器。

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

IoC在控制啥?反转啥?

由IoC控制对象实例的创建;

反转是针对正向而言,本来A需要自己找到外部B并自己实例化注入进来,现在A在等容器创建一个B的实例然后反向注入A,最后从容器中得到已注入B依赖的A实例。

IoC实例解析

IOC容器即服务容器。一个功能、命令或者任务都可以叫做服务service(一般指提供了一些功能的类)。如果把所有的服务(类)装在一个地方,那这个地方叫容器。

容器就是提供服务的载体,在程序运行过程中,动态的提供服务(资源)。

IoC容器实现解析案例

以下代码是小马整理的一个IOC容器案例解析,和Laravel的核心IOC基本相似,但有部分区别。

经典案例 Laravel Service Container 传送门

对以上代码的一些总结:

构造器注入:

总结:把闭包放入容器数组,使用时make调用闭包即可得到已经依赖注入的实例。

$bindings = []保存与接口绑定的闭包,闭包必须能够返回接口的实例。(存的是闭包,make运行闭包后即可得到实例。闭包函数在执行如果有依赖则依赖注入无则直接实例化,最终return实例化后的实例)

bind($abstract, $concrete = null)方法 可以理解为concrete  有两种:new class A实例化对象直接入容器和 calss类A,如果是class类则先反射,找到依赖B后new实例化B,并通过反射拿到被依赖的类A的实例化对象A,最后再加入容器。(即有依赖的反射找到被依赖的类B实例化后再实例化本身A,没有依赖的直接实例化A)

make运行闭包得到实例时,传入的参数是容器本身,即 $this

为某个接口绑定一个实现两种方式(有无依赖注入):

1. 绑定接口的实现的类名(student)

2. 绑定一个闭包,这个闭包应该返回接口的实例(teacher2)

两种方式的实例化操作都是调用 build() 方法完成

make方法是在用闭包得到一个最终的实例(new class)

其实还使用了注册树的设计模式。


放松一下

本次小马的分享就到这了,希望对大家有帮助,感谢。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容