面向对象分析与设计——对象模型


2           对象模型

 对象模型包括:抽象、封装、模块化、层次结构、类型、并发和持久

 

2.1   对象模型的演进

OO建立在以前技术的最佳思想之上。两大趋势:小规模→大规模;高级程序设计语言;

2.1.1    程序设计语言的换代

第一代(1954~1985):科学和工程应用,公式计算

FORTRANⅠ: 数学表达式

第二代(1959~1961):算法抽象

FORTRANⅡ:子程序、单独编译
ALGOL60:块结构、数据类型
COBOL:数据描述、文件处理
Lisp:列表处理、指针、垃圾收集,基于λ演算的函数式编程语言,在CAD软件上应用广泛(AUTOCAD二次开发用),括号+语法树;程序看作数据;          

第三代(1962~1970):数据抽象

Pascal:ALGOL60的简单继承者
Simula:类、数据抽象

代沟(1970~1980)

C:高效、可执行程序小
FORTRAN77:ANSI标准

OO兴盛(1980~1990)

Smalltalk:纯OO,在Smalltalk中所有的东西都是对象,或者应该被当作对象处理。例如表达式:2 + 3,应当被理解为:向对象2发送消息+,参数为对象3。                             对Objective-C、Java 、Ruby等有推动;开发思想:模式、XP、重构等
C++:从C和Simula发展而来

FrameWork的出现(1990~现在)

VB,Java,Python,J2EE,.NET,C#,VB.NET

 面向对象分析与设计——对象模型_第1张图片

2.1.2    第一代和第二代早期程序设计语言的拓扑结构

面向对象分析与设计——对象模型_第2张图片

基本物理构成单元:子程序(对COBOL而言,称之为段落)
物理结构 = 全局数据 + 子程序

2.1.3    第二代后期和第三代早期程序设计语言的结构

面向对象分析与设计——对象模型_第3张图片

子程序作为一种抽象机制
→ 开始发明支持参数传递机制的语言
→ 奠定了结构化设计的基础
在语言上支持嵌套子程序,并在控制结构和声明的可见性方面发展
→ 出现了结构化设计方法,利用子程序作为基本构建块 

2.1.4    第三代后期程序设计语言的结构

面向对象分析与设计——对象模型_第4张图片

大规模编译 → 独立开发同一程序的不同部分 → 独立编译的模块
此阶段,模块只是用于最有可能同时改变的子程序分组,非抽象机制
虽支持模块化,但鲜有规则要求模块间接口的语义一致性;
对数据抽象和强类型支持得不好,错误只有在运行期才能被检测出来。

2.1.5    基于对象和面向对象的程序设计语言的结构

面向对象分析与设计——对象模型_第5张图片              面向对象分析与设计——对象模型_第6张图片

                       中小型应用                                                   大型应用

 

构建块是模块,表现为逻辑上的一组类或对象,而非子程序。
过程、函数是动词,数据是名词 → 面向过程(procedure-oriented)围绕动词,OO围绕名词
中小型OO应用的物理结构表现为一个图,而非树;几乎无全局数据;数据和操作在单元中
对巨型编程,对象模型在规模上扩展;一组抽象可构建在另一组抽象层智商;一组抽象协作,实现更高层行为;即第一章中描述的复杂性的组成方式;

 

2.2   对象模型的基础

对象模型是普适的(UI/DB/computer architectures);
算法分解处理大量复杂问题时能力有限;
C++/JAVA作为面向算法使用会丧失威力;

何为对象:存在一些不变的特性,来刻画一个对象和它的行为;

2.2.1    面向对象编程

OOP的要点:    

  • 对象最为基本逻辑构建块;(组成层次结构)
  • 每个对象都是类的一个实例;
  • 类之间通过继承关联;(是一个层次结构)

支持OOP语言的需求:

  • 支持对象,这些对象具有命名的操作结构和隐藏的内部状态的数据抽象
    (It supports objects that are dataabstractions with an interface of named operations and a hidden local state.)
  • 对象有相关的类型[类]
  • 类型[类]可以从超类型(supertypes)[超类(superclasses)]中继承属性

2.2.2    面向对象设计

两个要点:

  • OOAD导致OO分解;(类和对象抽象VS结构化设计的算法抽象)
  • 使用不同表示法来表达系统逻辑特征(类和对象结构)和物理设计(模块和处理架构)的不同模型,以及系统的静态和动态特征 

2.2.3    面向对象分析

结构化分析关注系统中的数据流;OOA重点在构建真是世界的模型,开发更早阶段就考虑。

三方面的关系:OOA的结果作为开始OOD的模型,OOD的结果作为蓝图,利用OOP最终实现一个系统。

 

2.3   对象模型的要素

编程风格(programming style):一种组织程序的方式,基于某种编程概念模型和一种适合的语言,其目的是使得用这种风格编写的程序很清晰(away of organizing programs on the basis of some conceptual model of programming and an appropriate language to make programs written in the style clear)

  • 面向过程(Procedure) 算法;适用于计算密集型
  • 面向对象(Object)        类和对象;应用范围广,常作为架构框架
  • 面向逻辑(Logic)         目标,通常以谓词演算(predicate calculus)的方式表示;λ表达式,如Lisp,Prolog
  • 面向规则(Rule) 如果-那么(If–then)规则;适用于知识库
  • 面向约束(Constraint) 不变的关系(Invariant relationships)

对象模型的4个主要要素:抽象、封装、模块化、层次结构

3个次要要素:类型、并发、持久

 

2.3.1    抽象的意义

 抽象描述了一个对象的基本特征,可以讲这个对象与所有其他类型的对象区分开来,因此提供了清晰定义的概念边界,它与观察者的视角有关。
 抽象壁垒(abstraction barrier): 分离对象的基本行为和它的实现
最少承诺(least commitment): 对象的接口只提供它的基本行为
最少惊奇(least astonishment): 抽象捕捉某对象的全部(entire)行为,不多不少,不提供抽象之外的惊奇效果或副作用 

  • 实体抽象 问题域或解决方案域实体的一个有用的模型
  • 动作抽象 提供一组通用的操作,所有这些操作都有同类的功能
  • 虚拟机抽象 集中了某种高层控制要用到的所有操作,或这些操作将利用更低层的操作集
  • 偶然抽象 封装了一些相互间没有关系的操作 

从客户端角度,集中关注对象的外部试图
→     编程契约模型(contract model of programming)
→     外部视图定义了契约,其他对象依赖该契约,该对象通过内部视图来实现契约。契约包含了对象的责任,即它的可靠的行为

 

协议:可调用的操作集 + 合法的调用顺序;→ 构成了完整的静态和动态外部视图;
抽象思想的核心:不变性;前置条件(客户的责任) 后置条件(服务器的责任)


   C++:成员函数 = Smalltalk:方法(method) = Ada:操作(operation)

   C++:数据成员 = Smalltalk:实例变量(instance variable) = Java/Object Pascal:字段/域(filed)   

 

2.3.2    封装的意义

对象的抽象优先于实现决定;

       信息隐藏:对象的结构和方法的实现都是隐藏的;
       封装 → 不同抽象间提供了明确的边界 → 分离关注
       类的两部门:接口(描述外部视图,共同行为的抽象)+实现(抽象的表示,实现行为的机制)
       封装是一个过程,它分隔构成抽象的结构和行为的元素。封装的作用是分离抽象的概念接口及其实现。

2.3.3    模块化的意义

在程序内部创造一些定义良好的、有文档描述的边界(接口)
Smalltalk:无模块概念,类就组成了分解的唯一物理单元
Java:包;
C++:模块为独立的语言结构

       将逻辑上相关的类和对象放在同一个模块中。随意模块化比不实现模块化更糟;
       分解为模块的目标是:允许模块独立设计和修改,从而减少软件的成本。
       每个模块应足够简单:能被完全理解;在不知道其他模块的实现,并不影响其他模块行为的情况下,修改其实现。
       模块编译成本小,编译模块接口成本高 → 接口尽量小 

       模块化是一个系统的属性,这个系统被分解为一组高内聚、低耦合的模块。

2.3.4    层次结构的意义

层次结构是抽象的一种分级或排序。

  • 单继承:

类的两种客户:对象(调用类的实例方法),子类(继承该类)

封装被打破的三种方式:

子类可能访问其超类的实例变量;可调用其超类的私有操作;直接引用其超类的超类;

  •  多继承:

       混入类的概念?

       多重继承的问题:名字冲突、重复继承

名字冲突:不同超类具有同样名字的属性或操作

class A {
public:      
       A() { mVal = 1; }
       void F() {cout<<"A::F()"<


重复继承:钻石型继承

class A{
public:
       A (intx) : m_x(x) {}
       void F() {cout<<"A::F"<
在构建d对象时,里面存在两个A类基类子对象,尽管成员函数不存放在类中而在代码段,并且只会有一份,但是编译器不知道,他会作为两个继承函数来处理,用d.F()来访问时,编译器便不知道访问的是哪一个基类子对象里的F()     

解决方案:

class B : virtual public A//虚继承
class C : virtual public A//虚继承
D(int x) : B(x),C(x),A(x) {}

在这个过程中,A对象只在D的初始化表中A(x)进行构造(虚基类最先被构造),而在B和C的初始化表中不再对A进行构造(实际上是都有一个指针指向了D中的A(x),来对A进行构造) 

  • 聚合:

聚合允许对逻辑结构进行物理分组;而继承允许这些共同的部分在不同的抽象中被复用。
两种关系状态:
     植物园与植物(植物可独立存在,生命周期无关)
     植物园与培育计划(计划不可独立存在)

2.3.5    类型的意义

类型是关于一个对象的类的强制规定,不同类型的对象不能够互换使用,或至少它们的互换使用受到非常严格的限制。
利用多态可缓解运行时类型识别的需要。 

【类型一致性】:强类型、弱类型、无类型

强/弱类型是指类型检查的严格程度的。语言有无类型,弱类型和强类型三种。无类型的不检查,甚至不区分指令和数据。弱类型的检查很弱,仅能严格的区分指令和数据。强类型的则严格的在编译期进行检查。
强类型语言:在没有强制类型转化前,不允许两种不同类型的变量相互操作。
强类型的好处:更安全、早期错误检查、增强可读性、编译器生成的目标代码的效率更佳
强类型往往成为类型安全的同义词,然而,类型安全动态类型并不互相排斥。

【名字与类型绑定的时间】:静态类型(编译时固定)、动态类型(延迟绑定,运行时)

  • Ada: 强类型 + 静态类型
  • C++: 强类型 +支持动态类型
  • Java: 强类型 + 支持动态类型
  • Smalltalk: 无类型 + 动态类型
  • Perl、PHP: 弱类型 + 动态类型
  • Python: 强类型 + 动态类型

       一般而言,开发者社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。

       某些静态语言有一个“后门”,在这些编程语言中,能够编写一些不被静态类型所检查的代码。例如,Java和C-风格的语言有“转型”可用。在静态类型的编程语言中,不必然意味着缺乏动态类型机制。例如 Java 使用静态类型,但某些运算需要支持运行时期的类型测试,这就是动态类型的一种形式。

       C++是一种使用非常广泛的电脑程序设计语言。它是一种静态数据类型检查的,支持多范型的通用程序设计语言。C++支持过程化程序设计、数据抽象化、面向对象程序设计、泛型程序设计、基于原则设计等多种程序设计风格。

      C++ 的多态又分成静态多态(Static Polymorphism)与动态多态(DynamicPolymorphism)。动态多态必须结合继承和动态绑定(Dynamic Binding)方式实现。静态多态是指以模板(template)实现多态的方法,也就是参数化的型态(Parameterized Types),属于编译前(pre-compile)的多态,是使用宏(marco)的“代码膨胀法”达到多态效果。类型转换(type cast)也是一种区域(ad hoc)多态的概念,C++提供 dynamic_cast,static_cast等运算对象来实现类型转换(Coercion)。运算对象重载(operatoroverloading)或函数重载(function overloading)也算是多态的概念。

       C++是部分动态的,是编译时静态绑定,通过嵌入类(多重继承)和虚函数(虚表)来模拟实现

 

       JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。

       Java反射机制主要提供了以下功能:

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法;
  • 在运行时调用任意一个对象的方法;生成动态代理。

2.3.6    并发的意义

并发三级别:语言原生支持、使用类库、利用中断实现假象

----------------------------------------------------------

【并发concurrent VS 并行parallelism】

并发性是指两个或多个事件在同一时间段内发生
并行性是指两个或多个事件在同一时刻发生
并发性,又称共行性,是指能处理多个同时性活动的能力;
并行,是指同时发生的两个并发事件,具有并发的含义,而并发则不一定并行,也亦是说并发事件之间不一定要同一时刻发生。(如在同一个cpu上同时运行多个程序,不是真正的同时,而是看来是同时,因为cpu要在多个程序间切换)

线程机制支持并发程序设计,在多处理器系统上,它也能保证真正的并行处理

2.3.7    持久的意义

持久是对象的属性,它使得对象可以跨越时空存在。

持久的谱系:

        表达式计算的瞬时结果
        局部变量
        自由变量、全局变量、堆中的值
         ------------以上为传统编程语言关注的持久----------------
        程序执行之间存在的数据
        程序的不同版本之间存在的数据
        比程序生命期长的数据
        ------------以上通常为数据库技术关注的领域----------------

 

持久层(Persistence)

只是一个逻辑概念,即在系统逻辑层面上,专著于实现数据持久化的一个相对独立领域。负责向(或者从)一个或者多个数据存储器中存储/获取数据的一组类和组件。

数据持久化

一个动作,将内存中的数据模型转换为存储模型,就是把数据长期保存起来;以及,将存储模型转换为内存中的数据模型的统称.

数据模型

可以是任何数据结构或对象模型,存储模型可以是关系模型、XML、二进制流等。

表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)

DAO(DataAccess Object) 封装了访问数据库对象的接口,相当于一个通道,它可能会使用JDBC、Hinernate、iBatisa等工具来实现。而DAL 是指 Data Access Layer,是把所有和数据库操作(类似Insert、update、select)的业务逻辑封装,是一个逻辑上的概念,是为了设计规范、系统扩展方便的需要

Hibernate框架

是一个开放源代码的对象关系映射框架,它对JDBC(Java Data Base Connectivity,java数据库连接)进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。对象上数据的修改,Hibernate框架会把这种修改同步到数据库中。

附表:

对象模型元素

    特性     

     SmallTalk       

          C++          

         JAVA         

抽象(Abstraction)

实例变量

实例方法

类变量

类方法

    封装(Encapsulation)    

变量的

私有

公保私

公保私包

方法的

公开

公保私

公保私包

模块化(Modularity)

模块的种类

文件

文件

层次(Hierarchy)

继承

泛型单元

元类(Metaclasses)

类型化(Typing)

强类型化

    多态(Polymorphism)    

是(单)

是(单)

是(单)

并发(Concurrency)

多任务(Multitasking)

间接(通过类)

间接(通过类)

持久化(Persistence)

持久对象

 

2.4   应用对象模型

2.4.1    对象模型的好处

发挥基于对象和面向对象编程语言的能力
有利于软件复用,设计复用
有利于系统演化式发展,而非抛弃型重做
集成散布在生命周期的各个时刻
分离关注减少了开发风险

2.4.2    开放式问题

什么是类和对象?              第3章 类与对象
如何正确确定类和对象? 第4章 分类
怎样的表示法适合OOD? 第5章 表示法
怎样的过程可以得到结构良好的OO系统? 第6章 过程
使用OOD对管理层意味着什么? 第7章 实战

你可能感兴趣的:(读书随笔)