UML2面向对象分析与设计 -- 面向对象思维(概念、面向对象技术的发展历史、对象和类、面向对象技术的相关原则:抽象 封装 分解 泛化 多态 分层 复用)

1. UML2面向对象分析与设计 学习目标

  • OO(Object Oriented 面向对象):建立对象的思维方式,对面向对象思想和理论有深入的理解。
  • UML(Unified Modeling Language 统一建模语言):能够熟练地使用UML表达面向对象的设计思想。
  • Model(建模):运用面向对象的一般原则和模式进行应用系统的分析和设计建模。

2. 面向对象思维


2.1 学习目标

  • 从结构化到面向对象:理解传统结构化方法与面向对象方法之间的思维差异,掌握它们在具体应用中的区别和联系。
  • 从结构化到面向对象:理解传统结构化方法与面向对象方法之间的思维差异,掌握它们在具体应用中的区别和联系。
  • 对象和类:掌握并理解对象和类的定义及它们之间的关系。
  • 面向对象技术相关原则:掌握抽象、封装、分解、分层、复用等面向对象的基本原则,掌握并理解泛化和多态机制的作用。
  • 上升到面向对象:了解面向对象、建模和UML之间的关系,并对面向对象的建模要有一定的认识。

2.2 什么是面向对象

什么是面向对象技术?不同人从不同角度考虑就有不同的理解。可以认为:

  • 是一种处理计算机软件系统的观点
  • 是一种系统分析和设计的思想,或是一种编程方法
  • 是一组设计原则和模式

面向对象技术是一系列指导软件构造的原则(如抽象、封装、多态等),并通过语言、数据库和其他工具支持这些原则。从定义可以看出,从本质上讲,对象技术是对一系列相关原则的应用。有些书中采用“面向对象技术=类+对象+抽象+封装+继承+多态+消息……”这样更直观的形式定义面向对象技术。因此如果在应用过程中没有很好地利用这些思想,那么就不是面向对象。


2.3 面向对象技术的发展历史

  1. Simula语言:面向对象技术最早起源于1962—1967年出现的Simula 67语言,该语言是由Ole-Johan Dahl和Kristen Nygaard在挪威奥斯陆的国家计算中心设计实现的,它是世界上公认的第一种面向对象语言,在该语言中第一次提出了类、对象、封装等基本思想。
  2. malltalk语言:使面向对象技术进入实用化的标志则是1970年诞生的Smalltalk语言,它是由美国施乐公司的恪洛阿尔托研究中心(PARC)的Alan Kay设计实现的,是第一个成熟的面向对象语言,在这个语言中提供了完整的面向对象技术解决方案(诸如类、对象、抽象、封装、继承、多态等)。该语言的很多思想到现在还被广泛应用(如MVC、重构等)。
  3. C++语言:对象技术能够发展到今天这个地步,离不开1983年诞生的C++语言。正是因为C++语言的广泛应用,面向对象技术才真正从实验室阶段走到了商业化阶段,当今流行的Java、C#等面向对象的编程语言都有C++语言的影子。
  4. UML:面向对象技术发展初期成果还主要体现在面向对象编程语言的应用领域。然而随着软件工程技术的日益成熟和受到重视,在20世纪80年代末、90年代初,面向对象的软件工程也得到了迅速发展。在此期间,各种面向对象的方法层出不穷,这给普通用户的使用带来了很大的困扰。而1997年统一建模语言(UnifiedModeling Language, UML)的产生则标志着面向对象方法学的统一,从而为面向对象技术的应用扫清了最后一个障碍。此后,所有的软件工程师都可以使用他们的通用语言——UML来表达面向对象的思维。

2.4 面向对象技术的优势


2.4.1 便于沟通:在计算机中模拟现实世界的事和物

和传统结构化方法更侧重于计算机表达问题的能力不同,面向对象技术更顺应人类思维习惯,让软件开发人员在解空间(计算机环境)中直接模拟问题空间(现实世界)中的对象及其行为。这一特点使得开发人员能够更有效地在用户环境和实现环境之间进行转换,从而能够更加快速、有效地解决用户问题。

  • 早期汇编语言示例:
    在这里插入图片描述
  • 面向对象语言(例如Java)示例:
    在这里插入图片描述

可以发现面向对象语言非常的简单易懂,便于人们沟通。


2.4.2 稳定:较小的需求变化不会导致系统结构大的改变

面向对象技术的核心思想就是用稳定的元素将不稳定的元素封装起来,从而将变更的影响降到最低。在现实应用中,功能是最易变的,数据是较易变的,而对象则是较稳定的。


2.4.3 复用:提高质量,降低成本

面向对象技术通过封装、继承等手段,提供了各种不同层次的复用(如基于类库、框架等的代码层复用,基于抽象、多态、模式等设计层的复用),开发人员应该可以切身体会到面向对象复用所带来的好处。例如Java开发者通过调用庞大的Java类库,可以快速实现很多业务功能,而不需要进行太多的编码。这种基于复用的开发方法极大地提高了软件的开发效率,也大大降低了软件开发的难度。


2.4.4 其他优势

除了上面所提到的3个优势外,面向对象技术还有其他优势:

  • 改善软件结构,提高软件灵活性、增加可扩展性。
  • 支持增量式开发(强调软件在发布不同的版本时,每次都多发布一点点,是软件功能数量渐增地发布的程。)
  • 支持大型软件开发。

2.5 对象和类

面向对象技术是由一系列的概念和原则组成的,而这些概念和原则中的两个最基础、最重要的就是对象和类


2.5.1 对象

对象(Object)可以是一个实体、一件事、一个名词,也可以是可获得的某种东西,还可以是可想象为有自己标识的任何事物。对象的实体可以是物理存在的、也可能是一个概念,或是软件中的实体。例如,一辆卡车是一个物理上存在的实体;而一个化学反应过程则是一个概念中的实体;数据结构中的一个链表则是软件领域的实体。

正式定义:对象是一个实体,这个实体具有明确定义的边界(Boundary)和标识(Identity),并且封装了状态(State)和行为(Behavior)。

  • 对象具有明确定义的边界和标识:边界意味着对象是一个封装体,通过封装来与其他对象分隔。而标识则表明每一个对象都是唯一的,虽然有时候某个对象的状态有可能与其他对象一样。每个对象都是独一无二的,通过明确的边界与其他对象区分;同时,这个边界应该是研究该对象的用户可以清晰定义的。
  • 对象封装了状态和行为:对象的状态通过对象的属性(Attribute)和关系(Relationship)来表达。在实际应用中,对象的状态反映了现实世界的一系列属性,如属性的值(即与对象有关系的数据)、与其他对象的关系、任意一个时刻的历史状态。而对象的行为通过对象的操作(Operation)、方法(Method)和状态机(State Machine)来表达,它由对象定义的一系列操作来决定。它定义了当其他对象发出请求时,该对象如何反应。

在UML中,对象用矩形框表示,对象的名称写在矩形框内部,并加上下画线。UML中的对象有命名对象和匿名对象之分。

在这里插入图片描述

  • (a):J.Clark对象是Professor类的一个实例。
  • (b):匿名对象,该对象没有名称,只有所属的类名Professor,表示Professor类的某个对象。
  • (c):一个J.Clark对象,没有指定其所属的类,严格来说,这种只有对象名、没有类名的对象是错误的(因为在对象世界中,任何对象都来自类的实例化),但在早期的分析模型中可以使用,说明已知存在这样的一个对象,但尚未最终确定它所属的类。

2.5.2 类

类(Class)就是对一系列对象的抽象描述,这些对象共享相同的属性、操作、关系和语义。与此对应,一个具体的对象是该类的一个实例。由此可见,类是一种抽象,它将相似的实体抽象成相同的概念,这种抽象过程强调相关特征而忽略其他特征。

类抽象的过程就是将具体对象的特征和行为进行参数化,分别用类的属性操作表示。

  • 类的属性属性代表类的特征或特性,它表达了类所知道的事情。属性的值是某一特定对象的属性值。在类中,属性名必须是唯一的,同时每一个类的实例(即对象)都有为这个类定义的所有属性的值。
  • 类的操作:操作代表类知道和做的事情,它用于访问或修改对象的属性值。而对象的行为是由为此对象定义的一系列操作决定的。

对于一个类,其属性和操作并不是固定的,它们取决于类的应用场景,不同的使用目的决定了不同的抽象方式。

类和对象之间是紧密相关的,每一个对象都是某一个类的实例(类是生成对象的模板,类的定义中包含创建和删除对象的操作);而每一个类在某一时刻都有零个或更多个的实例存在。一个类通过一系列操作来定义行为,而该类的所有实例都可以使用在这个类中定义的操作。同时,类定义了使用哪些数据描述属性,每一个实例都需要定义具体的属性值。

在UML中,同样采用矩形框表示类,该矩形框可以划分为3个区域,分别表示类名、属性和操作

在这里插入图片描述
此外,类是静态的,它的存在、语义和关系在执行前就已经定义好了。而对象是动态的,在程序执行时可以被创建和删除。


2.6 面向对象技术的相关原则

对象和类作为面向对象技术的核心,存在着很多与之相关的原则,这些原则决定了面向对象技术的本质特征,只有遵循了这些原则,才是一个符合面向对象技术的方案。


2.6.1 抽象(面向对象系统中最难应用的一个关键技术)

从对象到类的过程就是抽象(Abstraction)的过程,即将所见到的具体实体抽象成概念,从而可以在计算机世界中进行描述和对其采取各种操作。

抽象过程并没有唯一的答案,同一个实体在不同的业务场景中可能有不同的抽象。同样是一批人,根据使用选课系统的目的不同,可以将其中的一部分人抽象为老师,而将另一部分人抽象为学生,这个过程与具体应用场景密切相关。这也是面向对象系统中最难应用的一个关键技术


2.6.2 封装(实现信息隐藏和数据抽象)

封装(Encapsulation)是指对象对其访问者隐藏具体的实现,它是软件模块化思想的体现。

通过封装实现信息隐藏和数据抽象。信息隐藏的出发点是对象的私有数据不能被外界存取,从而保证外界以合法的手段(对象所提供的操作)访问。同时,将数据抽象为一组行为,而不是内部的具体数据结构,把用户隔离在实现细节之外,从而使得软件各个部分依赖于抽象层,各模块获得自由。

示例:Java当中的封装

class Person {
	// 私有化成员变量
    private String name;

	// 提供 get / set 方法 为外面访问属性提供入口
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

2.6.3 分解(化繁为简 分而治之)

分解(Decomposition)是指将单个大规模复杂系统划分为多个不同的小构件。分解后的构件通过抽象和封装等技术形成相对独立的单元,这些单元可以独立地设计和开发,从而实现化繁为简分而治之,以应对系统的复杂性,降低软件开发成本。

在传统的结构化方法中,开发人员可以通过函数、模块等进行功能分解,实现模块化设计,可以通过耦合和内聚来判断分解的合理性,将系统分解为多个高内聚、低耦合的模块。而面向对象的分解则更为复杂,在基于类和对象分解的基础上,还需要进一步考虑类之间依赖程度、复用问题和稳定性问题等,进行合理的打包和分层,从而形成更加复杂的分解结构。

抽象、封装和分解是系统设计中3个最基本的原则,它们相辅相成。一个对象围绕着单一的抽象概念建立了一个封装体,而系统则可以被分解为多个对象,并对这些对象进行进一步打包,从而形成更高层的抽象概念。


2.6.4 泛化(继承关系)

泛化(Generalization)是类与类之间一种非常重要的关系,通过这种关系,一个类可以共享另外一个或多个类的结构和行为。为了实现泛化关系,我们引入了继承(Inheritance)机制。一个子类(Subclass)继承一个或多个父类(Superclass),从而实现了不同的抽象层次。这些层次之间所建立的is a或iskind of关系,即为泛化关系。通过这种关系可以很容易地复用已经存在的数据和代码,并实现多态处理。根据父类的个数不同,存在着单一继承和多重继承两种情况。

  • 单一继承(Single Inheritance)是指一个类继承另外一个类,图1-6展示了两个单一继承的实例,类Saving和类Account、类Checking和类Account通过单一继承构成两个泛化关系,表明一个存储账户(Saving)是一种账户(Account),一个支出账户(Checking)也是一种账户;它们都包含账户的信息(账号no、用户名name、余额balance),也都可以进行取款(Withdraw)操作。
    在这里插入图片描述

  • 多重继承(Multiple Inheritance)是指一个类继承另外多个类的属性和行为。如图1-7所示,类Bird同时继承类FlyingThing和类Animal,这是一个多重继承,表明鸟(Bird)即是一种飞行物(FlyingThing),又是一种动物(Animal)。
    在这里插入图片描述
    在实际系统应用中,对多重继承的使用一定要谨慎。因为有些编程语言(如Java)不支持多重继承,这会造成设计方案无法被实现。此外,即使像C++这样支持多重继承的语言,在实际应用过程中也会存在诸如名称冲突、二义性等问题。

一个子类会继承父类所有的元素(可能有些元素对于子类不可见),这包括属性、操作和关系。此外,子类还可以根据自己的需要添加额外的属性、操作或关系,还可对父类已有的操作进行重新定义。

下图展示了一种继承层次关系,其中子类(GraduateStudent)从父类(Student)继承,它继承了父类全部属性和操作,所以即使GraduateStudent中没有定义getName(),其也会从Student中得到getName()方法的全部实现。此外,子类也会继承父类中的关系,因此GraduateStudent与Account也有聚合关系。
在这里插入图片描述


2.6.5 多态(对象技术的根本特征)

多态(Polymorphism)是在同一外表(接口)下表现出多种行为的能力,它是对象技术的根本特征,是将对象技术称为面向对象的原因所在。对象技术正是利用多态提供的动态行为特征,来封装变化、适应变更,以达到系统的稳定目标。

图1-9展示了一个多态的应用案例。面向对象的多态必须要有泛化关系的支持(有的文献会把模板这种机制也称为多态,这种参数化多态不需要泛化关系支持),如Rectangle(矩形)和Circle(圆形)均继承自Shape(Shape以斜体字表示,表明该类是一个抽象类)。通过Shape提供的接口draw()实现画图功能的多态性,即根据目标的不同画出不同的形状。
在这里插入图片描述
现在假设有一个数组sharr,其中放着一排形状Shape,但不知道哪些是矩形,哪些是圆形。利用多态性,完全可以不关注这些细节,而直接画出目标形状(见下面代码)。
在这里插入图片描述

在遍历整个数组的过程中,各个Shape知道应当如何在画布上绘制自己的形状。shape.draw()这行代码在Shape指向不同的对象时将表现出不同的行为,这就是所谓多态。


2.6.6 分层

分层(Hierarchy)是指面向不同的目标建立不同的抽象级别层次,从而在不同的抽象层次对系统进行分解,进一步简化对系统的理解。在面向对象系统中,主要有两种层次结构:类层次结构和对象层次结构。

  • 类层次结构是指在不同的抽象级别进行对象的抽象,高层的类抽象层次更高,其描述能力也越强,而越往下抽象层次越低,底层的类则最具体,代表具体的事物。这些类之间通过泛化关系形成一种层次结构,也称为继承层次结构。此外,在这种层次结构中,一般同一层次的抽象级别是一样的。图1-10展示了一个继承层次结构的实例,最高层的父类(Food)抽象层次最高,代表所有类型的食物(Food);第二层的类(Fruit、Vegetable和Meat)则相对要具体一些,代表某一类食物,如水果(Fruit);而最低层的类抽象层次最低,为具体类,可以实例化对象,本图中代表具体的食物类型,如苹果(Apple)、橙子(Orange)等。前两层的类都是抽象类,不能构造具体的对象(UML类图中用斜体字表示)。
    在这里插入图片描述
  • 对象层次结构是指对象间的组成结构,即大的对象由小的对象组成(即分解成小的对象)。这种结构是通过类之间的聚合关系来实现的,也称为聚合层次结构。这一种整体和部分的关系是逐层分解思想的具体体现。图1-11给出了一个对象的聚合层次结构的实例,大学(University)由学院(School)和管理部门(Administration)组成,而学院又包含多个系(Department),每个系又由班级(Class)组成;管理部门则包括多个办公室(Office)。
    在这里插入图片描述

2.6.7 复用(缩减新软件开发和维护的成本)

复用(Reuse)是借助于已有软件的各种有关知识建立新的软件的过程,以缩减新软件开发和维护的成本。将软件看成是由不同功能部分的构件所组成的有机体,每个构件在设计编写时可以被设计成完成同类工作的通用工具,如果完成各种工作的构件被建立起来以后,编写特定软件的工作就变成了将各种不同构件进行组合的简单问题,从而对软件产品的最终质量和维护工作都有本质性的改变。“复用”是面向对象所带来的优势之一,而事实上要获得这种优势,在设计时就需要遵循复用的原则,设计可复用的构件。

在系统开发的各个阶段都可能涉及复用,如从最低层的代码复用到设计复用、架构复用,再到需求复用,甚至于延伸到特定业务领域的复用。复用原则要求设计者不仅针对当前的业务需求开展设计,还需要考虑业务的通用性和可扩展性等问题,从而设计抽象层次高、复用粒度大的组件。


2.7 建立面向对象思维

面向对象思维作为一种软件开发思想,对象技术是理论基础。引入对象技术的目的是能够有效地分析和设计软件系统,这个过程就是建模。为了表达建模结果,开发人员需要一种语言作为工具,这个工具就是统一建模语言(Unified Modeling Language, UML)。总的来说,建模是最终目的,对象技术是一种建模理论,而UML是一种体现面向对象思维的建模语言,它是将对象理论转换为实践的工具。



  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeJiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值