第七章:面向对象技术
面向对象技术
考点分析(上午题:占比16%,12分,下午题:UML建模、设计模式)
上午:面向对象基本概念、面向对象分析与设计、UML、设计模式
下午:用例图、类图与对象图、顺序图、活动图、状态图,java语法+设计模式或者C++语法+设计模式
面向对象基础
客观世界由许多具体的事物、事件、概念和规则组成,这些均可被看成对象。面向对象方法是一种非常实用的系统化软件开发方法,它以客观世界中的对象为中心,其分析和设计思想符合人们的思维方式,分析和设计的结果与客观世界的实际比较接近,容易被人们所接受。面向对象方法包括面向对象分析、面向对象设计和面向对象实现,其界线并不明显,它们釆用相同的符号表示,能方便地从分析阶段平滑地过渡到设计阶段。
面向对象的好处:解决了产品质量与生产率之间的权衡,使系统具有很高的灵活性和易扩充性,能管理复杂性并增强伸缩性,把某一领域分割成各种对象分析设计更合理,从概念模型化到分析、设计、编码可以实现无缝传递,通过封装进行信息隐蔽有助于建立安全的系统。
典型的面向对象设计语言:Smalltalk,Eiffel,C++,JAVA
面向对象的基本概念(Object-Oriented,OO)
对象:在面向对象的系统中,对象是基本的运行时的实体,它既包括数据(属性),也包括作用于数据的操作(行为)。所以,一个对象把属性和行为封装为一个整体。封装是一种信息隐蔽技术,它的目的是使对象的使用者和生产者分离,使对象的定义和实现分开。从程序设计者来看,对象是一个程序模块;从用户来看,对象为他们提供了所希望的行为。在对象内的操作通常称为方法。一个对象通常可由对象名、属性和方法3个部分组成。
消息:对象之间进行通信的一种构造叫作消息。
类:一个类定义了一组大体上相似的对象。一个类所包含的方法和数据描述一组对象的共同行为和属性。把一组对象的共同特征加以抽象并存储在一个类中是面向对象技术最重要的一点。类是在对象之上的抽象,对象是类的具体化,是类的实例(Instance)。
继承:继承是父类和子类之间共享数据和方法的机制。这是类之间的一种关系,在定义和实现一个类的时候,可以在一个已经存在的类的基础上进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。
抽象类:无实例的类,以供继承
多态:在收到消息时,对象要予以响应。不同的对象收到同一消息可以产生完全不同的结果,这—现象称为多态(Polymorphism)。在使用多态的时候,用户可以发送一个通用的消息,而实现 的细节则由接收对象自行决定。这样,同一消息就可以调用不同的方法。
绑定:绑定是一个把过程调用和响应调用所需要执行的代码加以结合的过程。在一般的程序设计语言中,绑定是在编译时进行的,叫作静态绑定。动态绑定则是在运行时进行的,因此,一个给定的过程调用和代码的结合直到调用发生时才进行。
消息传递:使对象具有交互能力的主要模型
对象自身引用(this):值使得方法体中引用的成员名与特定的对象相关;类型则决定了方法体被实际共享的范围
虚拟函数:只给出方法的定义不给出实现过程,供其子类重置(overriding)
类属:类的模版;参数多态机制;不限定成员的类型,具体对象再赋予具体类型
类库:预先定义的程序库,以程序模块的形式按照类层次结构把一组类的定义和实现组织在一起
面向对象分析:认定对象;组织对象;描述对象间的相互作用;定义对象的操作;定义对象的内部信息
面向对象设计:设计分析模型,实现相应源代码
面向对象软件的测试:算法层,类层,模版层,系统层
面向对象的方法:
1)OOA方法:主题层,对象类层,结构层,属性层,服务层
2)OOD方法:问题域部件,人机交互部件,任务管理部件,数据管理部件
3)Booch的OOD方法:标识类和对象,确定他们的含义,标识他们之间的关系,说明每一个类的界面和实现
4)OMT(面向对象建模技术):对象模型,动态模型,功能模型分析,系统设计,对象设计,实现
5)UML(统一建模语言):事务(结构事务、行为事务、分组事务、注释事务),关系(依赖、关联、泛化、实现),图(类图、对象图、用例图、交互图、状态图、活动图、构建图、部署图)
面向对象分析(Object-Oriented Analysis,OOA)
面向对象分析包含5个活动:认定对象、组织对象、描述对象间的相互作用、确定对象的操作、定义对象的内部信息。
面向对象设计(Object-Oriented Design,OOD)
面向对象设计的五大原则
1)开闭原则
对扩展开放,对修改关闭。多使用抽象类和接口,用抽象构建架构,用实现进行扩展。
2)单一职责原则
每个类应该实现单一的职责。保证一个类只做一件事,如拆分为实体类和Controller类等。
3)里氏替换原则
基类可以被子类替换。使用抽象类继承,不使用具体类继承,目的是增强程序的健壮性,实际项目中,每个子类对应不同的业务含义,使父类作为参数,传递不同的子类完成不同的业务逻辑。
4)依赖倒置原则
要依赖于抽象,不要依赖于具体。针对接口编程,不针对实现编程;抽象就是接口或者抽象类,细节就是实现类,上层模块不应该依赖下层模块,两者应依赖其抽象,抽象不应该依赖细节,细节应该依赖抽象,通俗点就是说变量或者传参数,尽量使用抽象类,或者接口,接口负责定义public属性和方法,并且申明与其他对象依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑。
5)接口隔离原则
使用多个隔离的接口,比使用单个接口好。建立最小的接口,接口的设计粒度越小,系统越灵活,但是灵活的同时结构复杂性提高,开发难度也会变大,维护性降低。
面向对象程序设计(Object-Oriented Programming,OOP)
程序设计范型(Programming Paradigm)是人们在程序设计时所采用的基本方式模型,决定了程序设计时采用的思维方式、使用的工具,同时又有一定的应用范畴。其发展经历了过程程序设计、模块化程序设计、函数程序设计、逻辑程序设计,发展到现在的面向对象程序设计范型。面向对象程序设计的实质是选用一种面向对象程序设计语言(Object-Oriented Programming Language,OOPL),采用对象、类及其相关概念所进行的程序设计。它的关键在于加入了类和继承性,从而进一步提高了抽象程度。特定的OOP概念一般是通过OOPL中特定的语言机制来体现的。
面向对象测试
UML
统一建模语言(Unified Modeling Language,UML)是一种为面向对象系统的产品进行说明、可视化和编制文档的一种标准语言,是非专利的第三代建模和规约语言。UML使用面向对象设计的的建模工具,但独立于任何具体程序设计语言。
事物
结构事物
结构事物是UML模型中的名词。它们通常是模型的静态部分,描述概念或物理元素。结构事物包括类(Class)、接口(Interface)、协作(Collaboration)、用例(Use Case)、主动类(Active Class)、构件(Component)、制品(Artifact)和结点(Node)。
行为事物
行为事物是UML模型的动态部分。它们是模型中的动词,描述了跨越时间和空间的行为。行为事物包括交互(Interaction)、状态机(State Machine)和活动(Activity)。各种行为事物的图形化表示如图所示。
分组事物
分组事物是UML模型的组织部分,是一些由模型分解成的“盒子”。在所有的分组事物中,最主要的分组事物是包(Package)。包是把元素组织成组的机制,这种机制具有多种用途。结构事物、行为事物甚至其他分组事物都可以放进包内。包与构件(仅在运行时存在)不同,它纯粹是概念上的(即它仅在开发时存在)。包的图形化表示如图所示。
注释事物
注释事物是UML模型的解释部分。这些注释事物用来描述、说明和标注模型的任何元素。注解是一种主要的注释事物。注解是一个依附于一个元素或者一组元素之上,对它进行约束或解释的简单符号。注解的图形化表示如图所示。
关系
关联关系
关联关系是类与类之间最常用的一种关系,表示一类对象与另一类对象之间有联系。组合、聚合也属于关联关系,只是关联关系的类间关系比其他两种要弱。关联关系有四种:双向关联、单向关联、自关联、多重数关联。例如:汽车和司机,一辆汽车对应特定的司机,一个司机也可以开多辆车。
在多重性关系中,可以直接在关联直线上增加一个数字,表示与之对应的另一个类的对象的个数。
单向关联
聚合关系
聚合关系也表示类之间整体与部分的关系,成员对象是整体对象的一部分,但是成员对象可以脱离整体对象独立存在。例如:公交车司机和工衣、工帽是整体与部分的关系,但是可以分开,工衣、工帽可以穿在别的司机身上,公交司机也可以穿别的工衣、工帽。
组合关系
组合关系表示类之间整体与部分的关系,整体和部分有一致的生存期。一旦整体对象不存在,部分对象也将不存在,是同生共死的关系。例如:人由头部和身体组成,两者不可分割,共同存在。
继承关系
继承关系中,子类继承父类的所有功能,父类所具有的属性、方法,子类应该都有。子类中除了与父类一致的信息以外,还包括额外的信息。例如:公交车、出租车和小轿车都是汽车,他们都有名称,并且都能在路上行驶。其类图如下:
实现关系
接口(包括抽象类)是方法的集合,在实现关系中,类实现了接口,类中的方法实现了接口声明的所有方法。例如:汽车和轮船都是交通工具,而交通工具只是一个可移动工具的抽象概念,船和车实现了具体移动的功能。
依赖关系
大多数情况下,依赖关系体现在某个类的方法使用另一个类的对象作为参数。依赖关系是一种“使用”关系,特定事物的改变有可能会影响到使用该事物的其他事物,在需要表示一个事物使用另一个事物时使用依赖关系。 例如:汽车依赖汽油,如果没有汽油,汽车将无法行驶。
六大关系完整图示
UML中的图
类图
类图(ClassDiagram)展现了一组对象、接口、协作和它们之间的关系。在面向对象系统的建模中所建立的最常见的图就是类图。
UML类图举例:
对象图
对象图(Object Diagram)展现了某一时刻一组对象以及它们之间的关系,描述了在类图中所建立的事物的实例的静态快照。
包图
包图(Package Diagram)是用于把模型本身组织成层次结构的通用机制,不能执行,展现由模型本身分解而成的组织单元以及其间的依赖关系。
构件图
构件图(Component Diagram)展现了一组构件之间的组织和依赖。
部署图
部署图(Deployment Diagram)是用来对面向对象系统的物理方面建模的方法,展现了运行时处理结点以及其中构件(制品)的配置。
组合结构图
组合结构图(Composite Structure Diagram)用于描述一个分类器(如类、构件或用例)的内部结构,分类器与系统中其他组成部分之间的交互端口,展示一组相互协作的实例如何完成特定的任务,描述设计、架构模式或策略。
活动图
活动图(ActivityDiagram)是一种特殊的状态图,它展现了在系统内从一个活动到另一个活动的流程。
状态图
状态图(State Diagram)展现了一个状态机,它由状态、转换、事件和活动组成。状态图关注系统的动态视图,对于接口、类和协作的行为建模尤为重要,强调对象行为的事件顺序。
用例图
用例图(Use Case Diagram)展现了一组用例、参与者(Actor)以及它们之间的关系。
用例描述
用例图只是简单地用图描述了一下系统,但对于每个用例,我们还需要有详细的说明,这样就可以让别人对这个系统有一个更加详细的了解,这时我们就需要写用例描述。对于用例描述的内容,一般没有硬性规定的格式,但一些必须或者重要的内容还是必须要写进用例描述里面的。用例描述一般包括:简要描述(说明)、前置(前提)条件、基本事件流、其他事件流、异常事件流、后置(事后)条件等等。下面说说各个部分的意思:
1)简要描述:对用例的角色、目的的简要描述;
2)前置条件:执行用例之前系统必须要处于的状态,或者要满足的条件;
3)基本事件流:描述该用例的基本流程,指每个流程都“正常”运作时所发生的事情,没有任何备选流和异常流,而只有最有可能发生的事件流;
4)其他事件流:表示这个行为或流程是可选的或备选的,并不是总要总要执行它们;
5)异常事件流:表示发生了某些非正常的事情所要执行的流程;
6)后置条件:用例一旦执行后系统所处的状态;
描述举例:
2019上半年软考 | 买书操作描述 |
---|---|
参与者 | 顾客 |
主要事件流 | ① 顾客登录系统 ② 顾客浏览书籍信息 ③ 顾客检查某种书籍的库存量是否为0 ④ 顾客选择所学购买的书籍及购买数量 ⑤ 系统检查库存量是否足够 ⑥ 系统显示验证界面 ⑦ 顾客验证 ⑧ 系统自动生成订单 |
备选事件流 | 1、若库存量为0则无法查询到书籍信息,退回到2 2、若购买数量超过库存量,则提示库存不足,并退回到4 3、若验证错误,则提示验证错误,并退回到6 4、若顾客需要可以选择打印订单 |
时序图
时序图描述对象之间消息的发送顺序,强调时间顺序。时序图是一个二维图,横轴表示对象,纵轴表示时间,消息在各对象之间横向传递,依照时间顺序纵向排列。用箭头表示消息、用竖虚线表示对象生命线。
UML时序图举例一:
UML时序图举例二:
1)角色(Actor):系统角色,可以是人、机器、其他系统、子系统,在时序图中用小人表示。
2)对象(Object)的三种命名方式:第一种方式包括对象名和类名,在时序图中,用“对象:类” 表示,第二种方式只显示类名,即表示它是一个匿名对象,在时序图中,用 “:类”表示, 第三种方式只显示对象名不显示类名,在时序图中,用“对象”表示。
命名方式的选择 :三种命名方式均可,哪种最容易让阅读该时序图的人理解,就选择哪种。
对象的排列顺序 :对象的左右顺序并不重要,但是为了作图清晰整洁,通常应遵循以下两个原则,第一把交互频繁的对象尽可能的靠拢,第二把初始化整个交互活动的对象放置在最左端。
3)生命线(Lifeline):在时序图中表示为从对象图标向下延伸的一条虚线,表示对象存在的时间。
4)控制焦点(Focus of Control):又称为激活期,表示时间段的符号,在这个时间段内对象将执行相应的操作。可以理解为Java语言中一对大括号{ }中的内容,用小矩形表示。
5)消息(Message):消息一般分为同步消息(Synchronous Message),异步消息(Asynchronous Message)和返回消息(Return Message)。 消息的发送者把控制传递给消息的接收者,然后停止活动,等待消息的接收者放弃或者返回控制,用来表示同步的意义。消息发送者通过消息把信号传递给消息的接收者,然后继续自己的活动,不等待接受者返回消息或者控制,异步消息的接收者和发送者是并发工作的。返回消息表示从过程调用返回。
6)自关联消息:表示方法的自身调用或者一个对象内的一个方法调用另外一个方法。
7)组合片段:组合片段用来解决交互执行的条件和方式,它允许在序列图中直接表示逻辑组件,用于通过指定条件或子进程的应用区域,为任何生命线的任何部分定义特殊条件和子进程。组合片段共有13种:
组合片段 | 说明 |
---|---|
Opt选项 | 包含一个可能发生或可能不发生的序列,可以在临界中指定序列发生的条件。 |
Alt抉择 | 包含一个片段列表,这些片段包含备选消息序列。在任何场合下只发生一个序列。可以在每个片段中设置一个临界来指示该片段可以运行的条件。 else的临界指示其他任何临界都不为True时应运行的片段。如果所有临界都为False且没有else,则不执行任何片段。 |
Loop循环 | 片段重复一定次数,可以在临界中指示片段重复的条件。Loop组合片段具有“Min”和"Max"属性,它们指示片段可以重复的最小和最大次数。默认值是无限制。 |
Break中断 | 如果执行此片段,则放弃序列的其余部分,可以使用临界来指示发生中断的条件。 |
Par并行 | 并行处理,片段中的事件可以交错。 |
Critical关键 | 用在Par或Seq片段中,指示此片段中的消息不得与其他消息交错。 |
Seq弱顺序 | 有两个或更多操作数片段,涉及同一生命线的消息必须以片段的顺序发生,如果消息涉及的生命线不同,来自不同片段的消息可能会并行交错。 |
Strict强顺序 | 有两个或更多操作数片段,这些片段必须按给定顺序发生。 |
Consider考虑 | 指定此片段描述的消息列表,其他消息可发生在运行的系统中,但对此描述来说意义不大。在"Messages"属性中键入该列表。 |
Ignore忽略 | 此片段未描述的消息列表,这些消息可发生在运行的系统中,但对此描述来说意义不大。在"Messages"属性中键入该列表。 |
Assert断言 | 操作数片段指定唯一有效的序列,通常用在Consider或Ignore片段中。 |
Neg否定 | 此片段中显示的序列不得发生,通常用在Consider或Ignore片段中。 |
Ref引用 | 引用其他地方定义的组合片段。 |
常用组合片段举例:
抉择(Alt)
选项(Opt)
循环(Loop)
并行(Par)
计时图(时间图)
时间图(Timing Diagram)是另一种新增的、特别适合实时和嵌入式系统建模的交互图,关注沿着线性时间轴、生命线内部和生命线之间的条件改变。它描述对象状态随着时间改变的情况,很像示波器,适合分析周期和非周期性任务。
交互概览图
交互概览图(Interaction Overview Diagram)是UML2.0新增的交互图之一,它是活动图的变体,描述业务过程中的控制流概览,软件过程中的详细逻辑概览,以及将多个图进行连接,抽象掉了消息和生命线。
通信图(协作图)
通信图(CommunicationDiagram)强调收发消息的对象的结构组织,在早期的版本中也被称作协作图。通信图强调参加交互的对象的组织。
设计模式
设计模式的要素
设计模式四要素:模式名称,问题,解决方案,效果
创建型模式与对象的创建有关,结构型模式处理类或对象的组合,行为型模式对类或对象怎样交互和怎样分配职责进行描述。