- OOAD 教程
- OOAD - 首页
- OOAD - 面向对象范式
- OOAD - 面向对象模型
- OOAD - 面向对象系统
- OOAD - 面向对象原则
- OOAD - 面向对象分析
- OOAD - 动态建模
- OOAD - 功能建模
- OOAD - UML 分析模型
- OOAD - UML 基本符号
- OOAD - UML 结构图
- OOAD - UML 行为图
- OOAD - 面向对象设计
- OOAD - 实现策略
- OOAD - 测试与质量保证
- OOAD 有用资源
- OOAD - 快速指南
- OOAD - 有用资源
OOAD - 实现策略
实现面向对象设计通常涉及使用标准的面向对象编程语言 (OOPL) 或将对象设计映射到数据库。在大多数情况下,它涉及两者。
使用编程语言实现
通常,将对象设计转换为代码的任务是一个简单的过程。任何面向对象编程语言,如 C++、Java、Smalltalk、C# 和 Python,都包含表示类的规定。在本章中,我们将使用 C++ 例举此概念。
下图显示了使用 C++ 表示 Circle 类。
实现关联
大多数编程语言不提供直接实现关联的构造。因此,实现关联的任务需要仔细考虑。
关联可以是单向的或双向的。此外,每个关联可以是一对一、一对多或多对多。
单向关联
在实现单向关联时,应注意维护单向性。不同多重性的实现如下所示 -
可选关联 - 在这里,参与对象之间可能存在或不存在链接。例如,在下图中,客户和活期账户之间的关联,客户可能拥有或不拥有活期账户。
对于实现,在 Customer 中包含一个 Current Account 的对象,该对象可能为 NULL。使用 C++ 实现 -
class Customer { private: // attributes Current_Account c; //an object of Current_Account as attribute public: Customer() { c = NULL; } // assign c as NULL Current_Account getCurrAc() { return c; } void setCurrAc( Current_Account myacc) { c = myacc; } void removeAcc() { c = NULL; } };
一对一关联 - 在这里,一个类的实例与关联类的正好一个实例相关联。例如,部门和经理之间存在一对一关联,如下面的图所示。
这是通过在 Department 中包含一个 Manager 对象来实现的,该对象不能为 NULL。使用 C++ 实现 -
class Department { private: // attributes Manager mgr; //an object of Manager as attribute public: Department (/*parameters*/, Manager m) { //m is not NULL // assign parameters to variables mgr = m; } Manager getMgr() { return mgr; } };
一对多关联 - 在这里,一个类的实例与关联类的多个实例相关联。例如,考虑 Employee 和 Dependent 之间的关联,如下面的图所示。
这是通过在 Employee 类中包含一个 Dependents 列表来实现的。使用 C++ STL 列表容器实现 -
class Employee { private: char * deptName; list <Dependent> dep; //a list of Dependents as attribute public: void addDependent ( Dependent d) { dep.push_back(d); } // adds an employee to the department void removeDeoendent( Dependent d) { int index = find ( d, dep ); // find() function returns the index of d in list dep dep.erase(index); } };
双向关联
要实现双向关联,需要维护两个方向的链接。
可选或一对一关联 - 考虑 Project 和 Project Manager 之间具有双向一对一关联的关系,如下面的图所示。
使用 C++ 实现 -
Class Project { private: // attributes Project_Manager pmgr; public: void setManager ( Project_Manager pm); Project_Manager changeManager(); }; class Project_Manager { private: // attributes Project pj; public: void setProject(Project p); Project removeProject(); };
一对多关联 - 考虑 Department 和 Employee 之间具有多对一关联的关系,如下面的图所示。
使用 C++ STL 列表容器实现
class Department { private: char * deptName; list <Employee> emp; //a list of Employees as attribute public: void addEmployee ( Employee e) { emp.push_back(e); } // adds an employee to the department void removeEmployee( Employee e) { int index = find ( e, emp ); // find function returns the index of e in list emp emp.erase(index); } }; class Employee { private: //attributes Department d; public: void addDept(); void removeDept(); };
将关联实现为类
如果关联有一些相关的属性,则应使用单独的类来实现它。例如,考虑 Employee 和 Project 之间的一对一关联,如下面的图所示。
使用 C++ 实现 WorksOn
class WorksOn { private: Employee e; Project p; Hours h; char * date; public: // class methods };
实现约束
类中的约束限制了属性可以取的值的范围和类型。为了实现约束,在从类实例化对象时,会为属性分配一个有效的默认值。每当在运行时更改值时,都会检查该值是否有效。无效值可以通过异常处理例程或其他方法来处理。
示例
考虑一个 Employee 类,其中 age 是一个属性,其值范围为 18 到 60。以下 C++ 代码包含了它 -
class Employee { private: char * name; int age; // other attributes public: Employee() { // default constructor strcpy(name, ""); age = 18; // default value } class AgeError {}; // Exception class void changeAge( int a) { // method that changes age if ( a < 18 || a > 60 ) // check for invalid condition throw AgeError(); // throw exception age = a; } };
实现状态图
有两种替代的实现策略来实现状态图中的状态。
类中的枚举
在这种方法中,状态由数据成员(或一组数据成员)的不同值表示。这些值由类中的枚举显式定义。转换由更改相关数据成员值的成员函数表示。
泛化层次结构中类的排列
在这种方法中,状态以一种可以由公共指针变量引用的方式排列在泛化层次结构中。下图显示了从状态图到泛化层次结构的转换。
对象映射到数据库系统
对象的持久性
开发面向对象系统的一个重要方面是数据的持久性。通过持久性,对象比创建它的程序具有更长的生命周期。持久性数据保存在辅助存储介质上,可以在需要时从那里重新加载。
RDBMS 概述
数据库是相关数据的有序集合。
数据库管理系统 (DBMS) 是一个软件集合,它有助于定义、创建、存储、操作、检索、共享和删除数据库中的数据。
在关系数据库管理系统 (RDBMS) 中,数据存储为关系或表,其中每一列或字段表示一个属性,每一行或元组表示一个实例的记录。
每一行都由一组称为主键的最小属性唯一标识。
外键是相关表的主键的属性。
在 RDBMS 中将类表示为表
要将类映射到数据库表,每个属性都表示为表中的一个字段。将现有属性(或属性)分配为主键,或添加一个单独的 ID 字段作为主键。类可以根据需要水平或垂直分区。
例如,Circle 类可以转换为如下所示的表。
Schema for Circle Table: CIRCLE(CID, X_COORD, Y_COORD, RADIUS, COLOR) Creating a Table Circle using SQL command: CREATE TABLE CIRCLE ( CID VARCHAR2(4) PRIMARY KEY, X_COORD INTEGER NOT NULL, Y_COORD INTEGER NOT NULL, Z_COORD INTEGER NOT NULL, COLOR );
将关联映射到数据库表
一对一关联
要实现 1:1 关联,任何一个表的主键都分配为另一个表的外键。例如,考虑 Department 和 Manager 之间的关联 -
创建表的 SQL 命令
CREATE TABLE DEPARTMENT ( DEPT_ID INTEGER PRIMARY KEY, DNAME VARCHAR2(30) NOT NULL, LOCATION VARCHAR2(20), EMPID INTEGER REFERENCES MANAGER ); CREATE TABLE MANAGER ( EMPID INTEGER PRIMARY KEY, ENAME VARCHAR2(50) NOT NULL, ADDRESS VARCHAR2(70), );
一对多关联
要实现 1:N 关联,关联 1 端的表的主键分配为关联 N 端的表的外键。例如,考虑 Department 和 Employee 之间的关联 -
创建表的 SQL 命令
CREATE TABLE DEPARTMENT ( DEPT_ID INTEGER PRIMARY KEY, DNAME VARCHAR2(30) NOT NULL, LOCATION VARCHAR2(20), ); CREATE TABLE EMPLOYEE ( EMPID INTEGER PRIMARY KEY, ENAME VARCHAR2(50) NOT NULL, ADDRESS VARCHAR2(70), D_ID INTEGER REFERENCES DEPARTMENT );
多对多关联
要实现 M:N 关联,将创建一个新的关系来表示关联。例如,考虑 Employee 和 Project 之间的以下关联 -
Works_On 表的模式 - WORKS_ON (EMPID, PID, HOURS, START_DATE)
创建 Works_On 关联的 SQL 命令 - CREATE TABLE WORKS_ON
( EMPID INTEGER, PID INTEGER, HOURS INTEGER, START_DATE DATE, PRIMARY KEY (EMPID, PID), FOREIGN KEY (EMPID) REFERENCES EMPLOYEE, FOREIGN KEY (PID) REFERENCES PROJECT );
将继承映射到表
要映射继承,基表的主键分配为派生表的主键和外键。
示例