OOAD - 对象模型

对象模型以对象的形式将软件应用程序中的元素可视化。 在本章中,我们将研究面向对象系统的基本概念和术语。

对象和类

对象和类的概念有着内在的联系,构成了面向对象范式的基础。

对象

对象是面向对象环境中的现实世界元素,可能具有物理或概念存在。 每个对象都有 −

  • 将其与系统中其他对象区分开来的标识。

  • 确定对象特征属性以及对象所拥有的属性值的状态。

  • 表示对象根据其状态变化执行的外部可见活动的行为。

可以根据应用程序的需要对对象进行建模。 一个物体可能有物理存在,如顾客、汽车等; 或无形的概念存在,如项目、流程等。

类表示具有相同特征属性并表现出共同行为的对象的集合。 它给出了可以从中创建的对象的蓝图或描述。 创建对象作为类的成员称为实例化。 因此,对象是类的实例。

类的组成部分是 −

  • 要从类实例化的对象的一组属性。 一般来说,一个类的不同对象的属性值有一定的差异。 属性通常称为类数据。

  • 描述类对象行为的一组操作。 操作也称为函数或方法。

示例

让我们考虑一个简单的类 Circle,它表示二维空间中的几何图形圆。 该类的属性可以如下识别 −

  • x-coord,表示中心的 x-坐标
  • y-coord,表示中心的 y-坐标
  • a,表示圆的半径

它的一些操作可以定义如下 −

  • findArea(),计算面积的方法
  • findCircumference(),计算周长的方法
  • scale(),增大或减小半径的方法

在实例化期间,至少为某些属性分配值。 如果我们创建一个对象 my_circle,我们可以指定 x-coord : 2、y-coord : 3 和 a : 4 等值来描述其状态。 现在,如果对 my_circle 执行缩放因子为 2 的scale()操作,则变量 a 的值将变为 8。该操作使 my_circle 的状态发生变化,即该对象表现出某种行为。

封装和数据隐藏

封装

封装是将属性和方法在类中绑定在一起的过程。 通过封装,类的内部细节可以对外部隐藏。 它允许只能通过类提供的接口从外部访问类的元素。

数据隐藏

通常,类的设计使其数据(属性)只能通过其类方法访问,并且与直接外部访问隔离。 这种隔离对象数据的过程称为数据隐藏或信息隐藏。

示例

在 Circle 类中,可以通过使属性在类外部不可见并向类添加另外两个方法来访问类数据来合并数据隐藏,即 −

  • setValues(),为 x 坐标、y 坐标和 a 赋值的方法
  • getValues(),检索 x 坐标、y 坐标和 a 值的方法

此处,对象 my_circle 的私有数据无法通过任何未封装在 Circle 类中的方法直接访问。 应该通过 setValues() 和 getValues() 方法来访问它。

消息传递

任何应用程序都需要许多对象以和谐的方式进行交互。 系统中的对象可以使用消息传递来相互通信。 假设系统有两个对象:obj1 和 obj2。 如果 obj1 希望 obj2 执行其方法之一,则对象 obj1 会向对象 obj2 发送一条消息。

消息传递的特点是 −

  • 两个对象之间的消息传递通常是单向的。
  • 消息传递支持对象之间的所有交互。
  • 消息传递本质上涉及调用类方法。
  • 不同进程中的对象可以参与消息传递。

继承

继承是一种机制,允许通过扩展和完善现有类的功能来从现有类创建新类。 现有的类称为基类/父类/超类,新的类称为派生类/子类/子类。 如果超类允许,子类可以继承或派生超类的属性和方法。 此外,子类可以添加自己的属性和方法,并且可以修改任何超类方法。 继承定义了"is – a"关系。

示例

从哺乳动物类中,可以派生出许多类,例如人类、猫、狗、牛等。人类、猫、狗和牛都具有哺乳动物的独特特征。 此外,每一种都有其独特的特点。 可以说,牛"是——一种"哺乳动物。

继承类型

  • 单一继承 − 子类派生自单个超类。

  • 多重继承 − 子类派生自多个超类。

  • 多级继承 − 子类派生自超类,而超类又派生自另一个类,依此类推。

  • 层次继承 − 一个类有多个子类,每个子类又可以有后续的子类,连续若干层,从而形成树形结构。

  • 混合继承 − 多重、多级继承的组合,形成格子结构。

下图描述了不同类型继承的示例。

继承

多态性

多态性最初是一个希腊词,意思是采取多种形式的能力。 在面向对象的范例中,多态性意味着以不同的方式使用操作,具体取决于它们所操作的实例。 多态性允许具有不同内部结构的对象具有共同的外部接口。 多态性在实现继承时特别有效。

示例

让我们考虑两个类,Circle 和 Square,每个类都有一个方法 findArea()。 尽管类中方法的名称和用途相同,但每个类的内部实现(即计算面积的过程)不同。 当 Circle 类的对象调用其 findArea() 方法时,该操作会查找圆的面积,而不会与 Square 类的 findArea() 方法发生任何冲突。

泛化和专业化

泛化和特化代表类之间关系的层次结构,其中子类继承自超类。

泛化

在泛化过程中,类的共同特征被组合起来形成更高层次的类,即子类被组合起来形成广义的超类。 它代表了一种"是-一种-种类"的关系。 例如,"汽车是一种陆地车辆",或者"船舶是一种水上车辆"。

特化

特化是泛化的逆过程。 在这里,对象组的区别特征用于从现有类中形成专门的类。 可以说,子类是超类的特化版本。

下图显示了泛化和特化的示例。

特化

链接和关联

链接

链接表示一个对象与其他对象进行协作的连接。 朗博将其定义为"物体之间的物理或概念联系"。 通过链接,一个对象可以调用方法或浏览另一对象。 链接描述了两个或多个对象之间的关系。

关联

关联是一组具有共同结构和共同行为的链接。 关联描述了一个或多个类的对象之间的关系。 链接可以定义为关联的实例。

关联度

关联度表示连接中涉及的类的数量。 次数可以是一元、二元或三元。

  • 一元关系连接同一类的对象。

  • 二元关系连接两个类的对象。

  • 三元关系连接三个或更多类的对象。

关联的基数比

二元关联的基数表示参与关联的实例数。 基数比分为三种类型,即 −

  • 一对一 − A 类的单个对象与 B 类的单个对象关联。

  • 一对多 − A 类的单个对象与 B 类的许多对象关联。

  • 多对多 − A 类的对象可以与 B 类的许多对象关联,反之,B 类的对象可以与 A 类的许多对象关联。

聚合或组合

聚合或组合是类之间的一种关系,通过这种关系,一个类可以由其他类的对象的任意组合组成。 它允许将对象直接放置在其他类的主体中。 聚合被称为"部分"或"具有一个"关系,能够从整体导航到其部分。 聚合对象是由一个或多个其他对象组成的对象。

示例

在"汽车有发动机"的关系中,汽车是整个物体或集合体,发动机是汽车的"一部分"。 聚合可以表示 −

  • 物理收容 − 例如,计算机由显示器、CPU、鼠标、键盘等组成。

  • 概念遏制 − 例如,股东拥有股份。

对象模型的好处

既然我们已经了解了与面向对象相关的核心概念,那么值得注意的是该模型必须提供的优势。

使用对象模型的好处是 −

  • 它有助于更快地开发软件。

  • 易于维护。 假设一个模块出现错误,那么程序员可以修复该特定模块,而软件的其他部分仍然正常运行。

  • 它支持相对轻松的升级。

  • 它可以重用对象、设计和功能。

  • 它降低了开发风险,特别是在复杂系统的集成方面。