对象模型包括:抽象、封装、模块化、层次结构、类型、并发和持久
OO建立在以前技术的最佳思想之上。两大趋势:小规模→大规模;高级程序设计语言;
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
基本物理构成单元:子程序(对COBOL而言,称之为段落)
物理结构 = 全局数据 + 子程序
子程序作为一种抽象机制
→ 开始发明支持参数传递机制的语言
→ 奠定了结构化设计的基础
在语言上支持嵌套子程序,并在控制结构和声明的可见性方面发展
→ 出现了结构化设计方法,利用子程序作为基本构建块
大规模编译 → 独立开发同一程序的不同部分 → 独立编译的模块
此阶段,模块只是用于最有可能同时改变的子程序分组,非抽象机制
虽支持模块化,但鲜有规则要求模块间接口的语义一致性;
对数据抽象和强类型支持得不好,错误只有在运行期才能被检测出来。
中小型应用 大型应用
构建块是模块,表现为逻辑上的一组类或对象,而非子程序。
过程、函数是动词,数据是名词 → 面向过程(procedure-oriented)围绕动词,OO围绕名词
中小型OO应用的物理结构表现为一个图,而非树;几乎无全局数据;数据和操作在单元中
对巨型编程,对象模型在规模上扩展;一组抽象可构建在另一组抽象层智商;一组抽象协作,实现更高层行为;即第一章中描述的复杂性的组成方式;
对象模型是普适的(UI/DB/computer architectures);
算法分解处理大量复杂问题时能力有限;
C++/JAVA作为面向算法使用会丧失威力;
何为对象:存在一些不变的特性,来刻画一个对象和它的行为;
OOP的要点:
支持OOP语言的需求:
两个要点:
结构化分析关注系统中的数据流;OOA重点在构建真是世界的模型,开发更早阶段就考虑。
三方面的关系:OOA的结果作为开始OOD的模型,OOD的结果作为蓝图,利用OOP最终实现一个系统。
编程风格(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)
对象模型的4个主要要素:抽象、封装、模块化、层次结构
3个次要要素:类型、并发、持久
抽象描述了一个对象的基本特征,可以讲这个对象与所有其他类型的对象区分开来,因此提供了清晰定义的概念边界,它与观察者的视角有关。
抽象壁垒(abstraction barrier): 分离对象的基本行为和它的实现
最少承诺(least commitment): 对象的接口只提供它的基本行为
最少惊奇(least astonishment): 抽象捕捉某对象的全部(entire)行为,不多不少,不提供抽象之外的惊奇效果或副作用
从客户端角度,集中关注对象的外部试图
→ 编程契约模型(contract model of programming)
→ 外部视图定义了契约,其他对象依赖该契约,该对象通过内部视图来实现契约。契约包含了对象的责任,即它的可靠的行为
协议:可调用的操作集 + 合法的调用顺序;→ 构成了完整的静态和动态外部视图;
抽象思想的核心:不变性;前置条件(客户的责任) 后置条件(服务器的责任)
C++:成员函数 = Smalltalk:方法(method) = Ada:操作(operation) C++:数据成员 = Smalltalk:实例变量(instance variable) = Java/Object Pascal:字段/域(filed) |
对象的抽象优先于实现决定;
信息隐藏:对象的结构和方法的实现都是隐藏的;
封装 → 不同抽象间提供了明确的边界 → 分离关注
类的两部门:接口(描述外部视图,共同行为的抽象)+实现(抽象的表示,实现行为的机制)
封装是一个过程,它分隔构成抽象的结构和行为的元素。封装的作用是分离抽象的概念接口及其实现。
在程序内部创造一些定义良好的、有文档描述的边界(接口)
Smalltalk:无模块概念,类就组成了分解的唯一物理单元
Java:包;
C++:模块为独立的语言结构
将逻辑上相关的类和对象放在同一个模块中。随意模块化比不实现模块化更糟;
分解为模块的目标是:允许模块独立设计和修改,从而减少软件的成本。
每个模块应足够简单:能被完全理解;在不知道其他模块的实现,并不影响其他模块行为的情况下,修改其实现。
模块编译成本小,编译模块接口成本高 → 接口尽量小
模块化是一个系统的属性,这个系统被分解为一组高内聚、低耦合的模块。
层次结构是抽象的一种分级或排序。
类的两种客户:对象(调用类的实例方法),子类(继承该类)
封装被打破的三种方式:
子类可能访问其超类的实例变量;可调用其超类的私有操作;直接引用其超类的超类;
混入类的概念?
多重继承的问题:名字冲突、重复继承
名字冲突:不同超类具有同样名字的属性或操作
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进行构造)
聚合允许对逻辑结构进行物理分组;而继承允许这些共同的部分在不同的抽象中被复用。
两种关系状态:
植物园与植物(植物可独立存在,生命周期无关)
植物园与培育计划(计划不可独立存在)
类型是关于一个对象的类的强制规定,不同类型的对象不能够互换使用,或至少它们的互换使用受到非常严格的限制。
利用多态可缓解运行时类型识别的需要。
【类型一致性】:强类型、弱类型、无类型
强/弱类型是指类型检查的严格程度的。语言有无类型,弱类型和强类型三种。无类型的不检查,甚至不区分指令和数据。弱类型的检查很弱,仅能严格的区分指令和数据。强类型的则严格的在编译期进行检查。
强类型语言:在没有强制类型转化前,不允许两种不同类型的变量相互操作。
强类型的好处:更安全、早期错误检查、增强可读性、编译器生成的目标代码的效率更佳
强类型往往成为类型安全的同义词,然而,类型安全与动态类型并不互相排斥。
【名字与类型绑定的时间】:静态类型(编译时固定)、动态类型(延迟绑定,运行时)
一般而言,开发者社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,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反射机制主要提供了以下功能:
并发三级别:语言原生支持、使用类库、利用中断实现假象
----------------------------------------------------------
【并发concurrent VS 并行parallelism】
并发性是指两个或多个事件在同一时间段内发生
并行性是指两个或多个事件在同一时刻发生
并发性,又称共行性,是指能处理多个同时性活动的能力;
并行,是指同时发生的两个并发事件,具有并发的含义,而并发则不一定并行,也亦是说并发事件之间不一定要同一时刻发生。(如在同一个cpu上同时运行多个程序,不是真正的同时,而是看来是同时,因为cpu要在多个程序间切换)
线程机制支持并发程序设计,在多处理器系统上,它也能保证真正的并行处理
持久是对象的属性,它使得对象可以跨越时空存在。
持久的谱系:
表达式计算的瞬时结果
局部变量
自由变量、全局变量、堆中的值
------------以上为传统编程语言关注的持久----------------
程序执行之间存在的数据
程序的不同版本之间存在的数据
比程序生命期长的数据
------------以上通常为数据库技术关注的领域----------------
持久层(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) |
持久对象 |
否 |
否 |
否 |
发挥基于对象和面向对象编程语言的能力
有利于软件复用,设计复用
有利于系统演化式发展,而非抛弃型重做
集成散布在生命周期的各个时刻
分离关注减少了开发风险
什么是类和对象? 第3章 类与对象
如何正确确定类和对象? 第4章 分类
怎样的表示法适合OOD? 第5章 表示法
怎样的过程可以得到结构良好的OO系统? 第6章 过程
使用OOD对管理层意味着什么? 第7章 实战