统一建模语言(Unified Modeling Language, UML)是软件业的标准语言。我们常见的软件通常都是面向对象的。复杂系统建模,需要调研需求、分析问题、设计解决方案等。在开发的每个阶段都应使用对象,使用对象可有效减少信息量,加强团队的协作交流。此篇为学习笔记整理备忘,了解的请忽略:)
本文主要整理了面向技术的最基础知识,设计了个栗子,介绍对象和类,并简要介绍了UML的类图和对象图。
目录
1. 为什么要面向对象
1.1 对象更便于人们理解
1.2 专业人员可以更好的交流
1.3 数据和过程不是人为分离的
1.4 代码更容易重用
2. 什么是对象
2.1 对象
2.2 类
3. 面向对象技术的相关原则
3.1 抽象
3.2 封装
3.3 泛化
3.4 多态
例如,在银行系统中,是根据银行账户、银行出纳员和顾客来编程,而不是直接深入账户记录、取款和存款过程、贷款资格的算法等。
无论是①修改别人的代码的程序员;②自己编写代码的高级程序员;③根据需要决定编写什么代码的设计师;还是④与客户交流,了解需求总结出最终完成的系统必须要做的工作的分析师。不同阶段的专业人士在交流时需要统一高效表达方式。在面向对象的方法中,每个人都使用相同的概念和表示法。而且,要处理的概念和表示法都比较少。
在传统方法中,需要存储的数据早早地与操作这些数据的算法分离开来,算法是独立开发的。从需要访问这些数据的过程来看,这会导致数据的格式不合适,或者数据放置的位肯不方便。而利用面向对象的开发方式,数据和过程一起放在容易管理的小软件包中,数据从来不与算法分开。最后得到的代码不太复杂,对客户而求的变化也不太敏感。
在传统方法中,是从要解决的问题开始,利用问题来驱动整个开发,最后得到当前问题的单个解决方案,但明天总是会有另一个问题要解决。无论新问题和已解决的旧问题多么接近,都不能分解单个系统,对它进行调整,因为一个小问题就会影响系统的每个部分。
最后,面向对象是成熟的,并已得到了证明。在面向对象的开发方式中,我们总是要在类似的系统中寻找有用的对象。对象就像是智力拼图玩具中的各块拼图。如果一块拼图变化了,就会影响临近的儿块拼图,但其他的拼图保持不变。
下面我们使用太阳系为例说明对象与类的关系和具体UML表示方法。
图片来自网络
对象(object)是一件事、一个实体、一个名词,可以获得的某种东西,可以想像有自己标识的任何东西。一些对象是活的,一些对象不是。现实世界中的例子有人、鸟、行星、银行账户或CV中能完成跟踪算法功能的模块等。
所有的对象都有属性(attribute), 例如人有姓名、身高、体重、性格;行星有直径、质量、轨道、表面温度、水分含量;跟踪算法有当前帧图像、跟踪框、模版、匹配分数等。对象还有行为(behavior):人会工作,行星会绕恒星运动;跟踪算法会更新目标位置。
在现实世界中,对象是具体存在的,但现实世界的对象常常和其他对象很相近。例如张三和李四都是人,鸽子和喜鹊都是鸟,地球和火星都是行星等。所以为了编程方便,对某一系列对象只应该定义一次,在需要时再创建具体的实体。类(Class)就是这一系列对象的抽象描述,这些对象共享相同的属性、操作、关系和语义。与此对应,一个具体的对象是该类的一个实例。由此可见,类是一种抽象,它将相似的实体抽象成相同的概念,这种抽象过程强调相关特征而忽略其他特征。
UML表示类的方式如下图所示。表示类的方框:第一格为类名,第二格为类的属性,第三格为类的行为、方法。例如Celestial body(天体)类有描述天体的如下属性:name(名字), size(大小), mass(重量), density(密度), composition(组成), location(位置);还有天体类的行为:move(运动)。属性或者方法前的+号表示public,-号表示private。属性后还可以用加上类型,例如name属性的类型是string字符串,添加方法为属性编辑区的type项后面输入。
用UML表示的对象如下图所示。左图的对象是“地球”使用“:”表示其属于Planet(行星)类;中图的对象没有名称,为匿名对象,表示行星类的某个对象;右图的对象“Venus”(金星)对象,没有指定所属的类。
试试看下面的对象分别是什么,属于哪一类?
世界是复杂的,为了处理这种复杂性,需要将其中的内容抽象化。抽象(Abstraction)的过程就是揭示事物区别千其他事物的本质特征的过程。是一个分析和理解问题的过程,这个过程取决于使用者的目的,它应该包括使用者所感兴趣的那些职责问题,而忽略掉其他不相关的部分。从对象到类的过程就是抽象的过程,即将所见到的具体实体抽象成概念,从而可以在计算机世界中进行描述和对其采取各种操作。抽象过程并没有唯一的答案,同一个实体在不同的业务场景中可能有不同的抽象。
封装(Encapsulation) 是指对象对其客户隐藏具体的实现,它是软件模块化思想的体现。通过封装实现信息隐藏和数据抽象。信息隐藏的出发点是对象的私有数据不能被外界存取,从而保证外界以合法的手段(对象所提供的操作)访问。同时,将数据抽象为一组行为,而不是内部的具体数据结构,把用户隔离在实现细节之外,从而使得软件各个部分依赖于抽象层,各模块获得自由,可以变化细节、可以进行替换。通过封装还可以保证数据的一致性;使用传统的结构化方法,是很难保证这一点的。
泛化(Generalization) 是类与类之间一种非常重要的关系,通过这种关系一个类可以共享另外一个或多个类的结构和行为。
为了实现泛化关系,采用继承(Inheritance)机制。一个子类(Subclass)继承一个或多个父类(Superclass),从而实现不同的抽象层次,这些层次之间所建立is a 或is kind of 关系,即为泛化关系。通过这种关系可以很容易地复用已经存在的数据和代码,并实现多态处理。根据父类的个数不同,存在着单一继承和多重继承两种情况。
单一继承(Single Inheritance) 是指一个类继承另外一个类,下图展示了单一继承的实例,类Star(恒星)和类Celestial body(天体),类Planet(行星)和类Celestial body 、类Moon(卫星)和类Celestial body,分别通过单一继承构成3个泛化关系。表明一个恒星类、一个行星类和一个卫星类。三者都是天体。
很自然的有单一继承就有多重继承。多重继承(Multiple Inheritance)是指一个类继承另外多个(超过一个)类的属性和行为。如下图所示,类Planet同时继承类Celestial body和类Ball,这是一个多重继承,表明行星(Planet) 既是一种天体(Celestial body),又是一种球体(Ball) 。
多态(Polymorphism) 是在同一外表(接口)下表现出多种行为的能力,它是对象技术的根本特征,是将对象技术称为面向对象的原因所在。对象技术正是利用多态提供的动态行为特征,来封装变化,适应变更,以达到系统的稳定。
可以这样认为,一个子类会继承父类所有的元素(可能有些元素对于子类不可见),这包括属性、操作和关系。此外,子类还可以根据自己的需要添加额外的属性、操作或关系,还可对父类已有的操作进行重新定义。
例如下图所示的多态示例。多态需要有泛化关系的支持,如行星和卫星均继承自天体(斜体字表示其为抽象类)。通过天体提供的接口move()实现运动行为的多态性,即根据目标的不同做出不同的运动。如,行星的运动为自转和公转相结合,而卫星没有自转。
假设有个数组array,其中放着一些天体,但不知哪些是行星,哪些是卫星。利用多态性,完全可以不用关注这些细节,而直接让它们嗨起来。
for(int i = 0; i < array.length; ++i)
{
CelestialBody cBody = (CelestialBody)array[i];
cBody.move();
}
在遍历整个数组的天体过程中,各个天体知道自己该怎样转。所以cBody.move()这行代码在cBody指向不同类的天体时,将表现出不同的行为,这就是多态。
本文引用与更新链接:https://blog.csdn.net/iracer/article/details/104788317
相关文章:
1.一起学UML建模:UML简介与建模软件安装:https://blog.csdn.net/iracer/article/details/104686010
2.一起学UML建模:面向对象基础与UML表示:https://blog.csdn.net/iracer/article/details/104788317