精华内容
下载资源
问答
  • C++是从C语言发展演变而来的一种面向对象程序设计语言。面向对象程序设计方法将数据及对数据的操作方法封装在一起,作为一个相互依存、不可分离的整体——对象。对同类型对象抽象出其共性,形成类。类通过外部...
    清华大学视频课件:面向对象程序设计(C++)(自主模式)
    课程简介
    C++是从C语言发展演变而来的一种面向对象的程序设计语言。面向对象的程序设计方法将数据及对数据的操作方法封装在一起,作为一个相互依存、不可分离的整体——对象。对同类型对象抽象出其共性,形成类。类通过外部接口,与外界发生关系,对象与对象之间通过消息进行通讯。这样,程序模块间的关系简单,程序模块的独立性、数据的安全性具有良好的保障,通过继承与多态性,使程序具有很高的可重用性,使得软件的开发和维护都更为方便。
    由于面向对象方法的突出优点,目前它已经成为开发大型软件时所采用的主要方法。而C++语言是应用最广泛的面向对象的程序设计语言之一。
    本课程是一门面向广大初学者的入门课程,自1999年开始在清华大学开设,本课程的教材已经在清华大学等一百多所学校的不同专业中使用,取得了良好的教学效果。
    本课程将C++语言作为大学生的计算机编程入门语言,不仅详细介绍语言本身,而且介绍常用的数据结构和算法、面向对象的设计思想和编程方法。课程以面向对象的程序设计方法贯穿始终,每一章都是首先阐述面向对象的程序设计思想和方法,由实际问题入手,然后引出必要的语法知识,在讲解语法时着重从程序设计方法学的角度讲述其意义和用途。
    本课程是清华校内同名课程的完整版,内容全面,难度适中,包括了ISO第三版C++标准(C++11)的新内容。
    徐明星,博士,副教授。国家级精品课程“程序设计基础”课程负责人、国家级精品资源共享课“计算机语言与程序设计”建设负责人。主讲《程序设计基础》、《面向对象程序设计基础》、《信号处理原理》等计算机专业基础课程。作为主要成员参与编写的《程序设计基础(第3版)》(清华大学出版社出版)评为普通高等教育“十二五”规划教材。曾获北京市高等教育教学优秀成果一等奖、清华大学青年教师教学优秀奖、清华大学清韵烛光“学生最喜爱的老师”称号。主要研究兴趣包括:语音识别与理解、情感计算和跨媒体计算等。目前,作为项目负责人承担国家自然科学基金面上项目1项;作为项目骨干或子课题负责人参与国家973项目1项、自然科学基金重点项目1项、社会科学基金重点项目1项、863项目1项。
    课程章节
    直接点击博客网页连接就可以进入下载页面,点击后可能会多次弹出广告页面,请量解,点击普通下载。
    点击普通下载。
    将网址复制粘贴到浏览器地址栏,点击后可能会有广告,请量解,点击普通下载。
    第一讲 课程简介与编程环境
    第二讲 基础语法(1)
    第三讲 基础语法(2)
    第四讲 基础语法(3)
    第五讲 找到对象,确定接口 
    5.1 从FOP到OOP  
    第六讲 算法横向拆分,分离步骤
    第七讲 算法纵向拆分,分离表示
    第八讲 基于接口组合,应对复杂变化
    第九讲 增加抽象层级,隔离复杂变化
    QQ:2774494285 。


    展开全文
  • 面向对象程序设计六大原则

    千次阅读 2017-07-11 17:16:23
    面向对象程序设计中,需要遵守的原则可总结为6个,这就是大名鼎鼎的六大原则。面向对象程序设计原则也是我们用于评价一个设计模式的重要指标之一。在设计模式中,很多设计模式都遵守了这些原则。 单一职责原则...

    面向对象程序设计中,需要遵守的原则可总结为6个,这就是大名鼎鼎的六大原则。面向对象程序设计原则也是我们用于评价一个设计模式的重要指标之一。在设计模式中,很多设计模式都遵守了这些原则。

    1. 单一职责原则(Single Responsibility Principle)
    2. 里氏替换原则(Liskov Substitution Principle)
    3. 依赖倒置原则(Dependence Inversion Principle)
    4. 接口隔离原则(Interface Segregation Principle)
    5. 迪米特法则(Law Of Demeter)
    6. 开闭原则(Open Close Principle)

    单一职责原则

    什么是单一职责原则
    单一职责原则(Single Responsibility Principle, SRP):即一个类只负责相应领域的职责,即不要存在多于一个导致类变更的原因。(There should never be more than one reason for a class to change。)

    起源
    罗伯特·C·马丁(Robert C. Martin)于《敏捷软件开发:原则、模式和实践》一书中给出。马丁表示此原则是基于汤姆·狄马克(Tom DeMarco)和Meilir Page-Jones的著作中的内聚性原则发展出的。

    为什么要使用单一职责原则
    一个类承担的职责越多,当一个职责变化时,其他职责受到影响的可能性就越大,软件出现错误的可能性就越大。

    优点

    • 降低类的复杂度。一个只有一个职责的类肯定比有多个职责的类要简单。
    • 降低因职责修改带来的风险。

    缺点

    • 说是缺点其实不准确。在实际操作中,想要遵循单一职责原则总是受到种种约束。要注意,原则是死的,人是活的,要根据实际情况来决定是否要遵循单一职责原则。

    问题
    1.有哪些设计模式遵循了单一职责原则

    • 迭代器模式。将聚合器类的遍历职责剥离出来,使聚合器类遵守“单一职责原则”。

    欢迎补充。

    里氏替换原则

    什么是里氏替换原则(Liskov Substitution Principle,LSP)
    严格定义:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。

    通俗定义:任何基类可以出现的地方,子类一定可以出现。

    为什么要遵守里氏替换原则
    LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。

    如何遵守里氏替换原则
    在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。

    优点
    待补充

    缺点
    待补充

    问题
    1.有哪些设计模式遵循了里氏替换原则

    待补充。

    依赖倒置原则

    什么是依赖倒置原则(Dependency Inversion Principle, DIP)
    依赖倒置原则两个要点:

    • 高层次的模块不应该依赖于低层次的模块,两者应该依赖于抽象。
    • 抽象不应该依赖于具体实现,具体实现应该依赖于抽象。

    为什么要遵守依赖倒置原则
    依赖倒置原则(Dependence Inversion Principle)要求程序依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程。一般情况下抽象的变化概率很小,让用户程序依赖于抽象,实现的细节也依赖于抽象。即使实现细节不断变动,只要抽象不变,程序就不需要变化。这大大降低了调用方与实现细节的耦合度。

    如何遵守依赖倒置原则

    • 变量的声明类型尽量是抽象类或接口。
    • 被引用的模块尽量都要有抽象类或接口,或者两者都有,引用它们时使用它们的抽象。

    优点
    待补充

    缺点
    待补充

    问题
    1.有哪些设计模式遵循了依赖倒置原则

    欢迎补充。

    接口隔离原则

    什么是接口隔离原则(Interface Segregation Principle, ISP)

    • 客户端不应该依赖它不需要的接口。
    • 一个类对另一个类的依赖应该建立在最小的接口上。

    为什么要遵守接口隔离原则
    需要什么用什么,把客户端不需要用的东西放在接口里,对客户端没有好处,而且需要承担这些不需要的东西所带来的风险。

    如何遵守接口隔离原则
    尽量细化接口,接口中的方法尽量少。即为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。

    优点
    待补充

    缺点
    待补充

    问题

    1.有哪些设计模式遵循了接口隔离原则
    欢迎补充。

    迪米特法则

    什么是迪米特法则
    迪米特法则(Law of Demeter,LoD),又叫作最少知道原则(Least Knowledge Principle,LKP)。就是说一个对象应当对其他对象保持最少的了解。

    为什么要遵守迪米特法则
    类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易。

    如何遵守迪米特法则
    尽量降低类与类之间的耦合。

    优点
    待补充

    缺点
    待补充

    问题

    1.有哪些设计模式遵循了迪米特法则

    • 外观模式。外观模式对客户端屏蔽子系统,客户端不需要了解子系统,直接访问外观类即可。
    • 责任链模式。请求发送者只负责创建责任链,不需要知道请求被哪个处理者处理,怎样处理。
    • 命令模式。请求者和接受者之间不存在直接引用,实现了解耦。
    • 中介者模式。中介者模式将各同事解耦,实现了“一个对象应当对其他对象保持最少的了解”。
    • 观察者模式。观察者和目标是抽象耦合的。目标只是维持了一个观察者的集合,而不知道任何一个观察者是属于哪个具体的类的。这样目标和观察者之间的耦合是最小的。

    认知有限,欢迎补充。

    开闭原则

    什么是开闭原则
    开闭原则(Open Closed Principle):一个软件实体应该对扩展开放,对修改关闭。

    软件实体
    软件实体指的是如类、模块和函数。

    为什么要遵守开闭原则
    需求的变动是任何一软件系统都难以避免的问题,在需求变动时,如果软件系统遵守开闭原则,那么就能不修改原有代码,而是在现有的代码的基础上进行扩展。在软件规模越来越大,寿命越来越长的今天,遵守开闭原则变得尤其重要。

    如何遵守软件符合开闭原则
    抽象化。

    优点
    待补充

    缺点
    待补充

    问题

    1.有哪些设计模式遵循了开闭原则

    • 工厂方法模式。在工厂方法模式中,当需要新增一种产品时,只需要新增一个产品类和工厂类即可,不需要修改原有代码。
    • 抽象工厂模式。增加新的具体工厂和产品族很方便,无须修改已有系统。
    • 建造者模式。指挥者类针对抽象建造者类编程,增加新的具体建造者无须修改原有类库的代码,系统扩展方便。
    • 适配器模式。可以在不修改原有代码的基础上增加新的适配器类。
    • 桥接模式。在抽象部分和实现部分两个变化维度中任意扩展一个维度,都不需要修改原有代码。
    • 组合模式。在组合模式中新增叶子构件和容器构件都很方便。
    • 装饰模式。客户端可以根据具体需要添加具体构建类和具体装饰类,并进行组合。
    • 责任链模式。想要新增一个处理者,只需要在客户端中重新建立链即可,原有系统不需要修改。
    • 命令模式。加入新的具体命令类不会影响原有系统。
    • 解释器模式。在解释器模式中,增加新的解释表达式较为方便。如果需要增加新的解释表达式,只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改。
    • 迭代器模式。由于有抽象聚合类和抽象迭代器类,添加新的聚合类和迭代器都不需要修改原有代码。
    • 中介者模式。如果需要引入新的具体同事类,只需要继承抽象同事类并实现其中的方法即可,由于具体同事类之间并无直接的引用关系,因此原有所有同事类无须进行任何修改,它们与新增同事对象之间的交互可以通过修改或者增加具体中介者类来实现。如果需要增加新的具体中介者类,只需要继承抽象中介者类(或已有的具体中介者类)并覆盖其中定义的方法即可,在新的具体中介者中可以通过不同的方式来处理对象之间的交互,也可以增加对新增同事的引用和调用。
    • 观察者模式。可以在不修改原有系统的条件下灵活的新建新的策略。
    • 模板方法模式。可以在不修改原有代码的前提下灵活的新增具体子类。
    • 部分遵守开闭原则。为什么说部分遵守呢?因为新增新的访问操作很方便,仅需要增加一个新的访问者即可在一个对象结构上定义一个新的操作。但如果需要新增元素类,要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作。

    欢迎补充。

    展开全文
  • 程序设计语言诞生  1946冯·诺依曼提出了冯·诺依曼原理:  CPU逐条从存储器中取出指令执行,按指令取出存储的数据经运算后送回。  数据指令(存储地址码、操作码)都统一按二进制编码输入。数据值的改变是重新...

    程序设计语言诞生

            1946冯·诺依曼提出了冯·诺依曼原理:

            CPU逐条从存储器中取出指令执行,按指令取出存储的数据经运算后送回。

           数据和指令(存储地址码、操作码)都统一按二进制编码输入。数据值的改变是重新赋值,即强行改变数据存储槽的内容,所以说它是命令式的(imperative)。

            第一台按冯·诺依曼原理制成的通用电动计算机是1951年美国兰德公司的UNIVAC-1。人们就开始了机器语言的程序设计: 指定数据区编制一条条指令。由于任何人也无法记住并自如地编排二进制码(只有1和0的数字串),则用8、16进制数写程序,输入后是二进制的。

           单调的数字极易出错,人们不堪其苦,想出了将操作码改作助记的字符,这就是汇编语言,汇编语言使编程方便得多。但汇编码编的程序必须要通过汇编程序翻译为机器码才能运行。尽管汇编码程序和机器码程序基本一一对应,但汇编语言出现说明两件事,一是开始了源代码——自动翻译器——目标代码的使用方式,一是计算机语言开始向宜人方向的进程。

     

    50年代高级语言出现

     

          1954年Backus根据1951年Rutishauser提出的用编译程序实现高级语言的思想,研究出第一个脱离机器的高级语言FORTRAN I。其编译程序用18个人一年完成(用汇编语言写)。到1957年的FORTRAN Ⅱ,它就比较完善了。它有变量、表达式、赋值、调用、输入/输出等概念; 有条件比较、顺序、选择、循环控制概念; 有满足科技计算的整、实数、复数和数组,以及为保证运算精度的双精度等数据类型。表达式采用代数模型。

           FORTRAN的出现使当时科技计算为主的软件生产提高了一个数量级,奠定了高级语言的地位。FORTRAN也成为计算机语言界的英语式世界语。

           1958年欧洲计算机科学家的一个组织GAMM和美国计算机协会ACM的专家在苏黎士会晤起草了一个“国际代数语言IAL”的报告,随后这个委员会研制了ALGOL 58得到广泛支持和响应。1960年欧美科学家再度在巴黎会晤对ALGOL 58进行了补充,这就是众所周知的ALGOL 60。1962年罗马会议上对ALGOL 60再次修订并发表了对“算法语言ALGOL 60修订的报告”。由于该报告对ALGOL 60定义采用相对严格的形式语法。ALGOL语言为广大计算机工作者接受,特别在欧洲。在美国,IBM公司当时经营世界计算机总额75%的销售量,一心要推行FORTRAN,不支持ALOGL,以致ALGOL 60始终没有大发展起来。尽管如此,ALGOL 60还是在程序设计语言发展史上是一个重要的里程碑。

           1959年为了开发在商用事务处理方面的程序设计语言,美国各厂商和机构组成一个委员会。在美国国防部支持下于1960年4月发表了数据处理的COBOL 60语言。开发者的目标要尽可能英语化,使没有计算机知识的老板们也能看得懂。所以像算术运算符+、*都用英文ADD、MULTIPLY。COBOL 60的控制结构比FORTRAN还要简单,但数据描述大大扩展了,除了表(相当于数组)还有纪录、文件等概念。COBOL 60虽然繁琐(即使一个空程序也要写150个符号),由于其优异的输入/出功能,报表、分类归并的方便快速,使它存活并牢固占领商用事务软件市场,直到今天在英语国家的商业领域还有一定的地位。

           50年代计算机应用在科学计算和事务处理方面有了FORTRAN、COBOL,因而应用得到迅速发展。工程控制方面刚刚起步,仍是汇编语言的市场。1957年,美国MIT科学家McCarthy提出LISP,并把它用于数学定理验证等较为智能性的程序上。但LISP在当时只是科学家的语言,没有进入软件市场。

     

    60年代奠基性研究

     

            60年代计算机硬件转入集成电路成本大幅度下降。应用普及的障碍是语言及软件。这就促使对编译技术的研究。编译技术的完善表现在大型语言、多种流派语言的出现。

           1962年哈佛大学的K. Iverson提出APL语言。它是面向数学(矩阵)的语言。它定义了一套古怪的符号,联机使用非常简洁,深得数学家喜爱。它提出动态数据(向量)的概念。

           1962年AT&T公司贝尔试验室R.Griswold提出正文处理的SNOBOL,可以处理代数公式、语法、正文、自然语言。以后发展为SNOBOL 3,SNOBOL 4。80年代后裔叫ICON,用于测试。

           1963-64年美国IBM公司组织了一个委员会试图研制一个功能齐全的大型语言。希望它兼有FORTRAN和COBOL的功能,有类似ALGOL 60完善的定义及控制结构,名字就叫程序设计语言PL/1。程序员可控制程序发生异常情况的异常处理、并行处理、中断处理、存储控制等。所以它的外号叫“大型公共汽车”。它是大型通用语言的第一次尝试,提出了许多有益的新概念、新特征。但终因过于复杂、数据类型自动转换太灵活、可靠性差、低效,它没有普及起来。但IBM公司直到80年代在它的机器上还配备PL/I。

           1967年为普及程序语言教育,美国达特茅斯学院的J.G. Kemeny和T.E.Kurtz研制出交互式、解释型语言BASIC(“初学者通用符号指令码”字头)。由于解释程序小(仅8K)赶上70年代微机大普及,BASIC取得众所周知的成就。但是它的弱类型、全程量数据、无模块,决定了它只能编制小程序。它是程序员入门的启蒙语言。

           LOGO语言是美国MIT的S. Papert教授于1967年开发的小型语言。其目的是无数学基础的青少年也能学习使用计算机,理解程序设计思想,自己编制过程或程序。但直到80年代初微机普及到家庭它才受到重视。LOGO是交互式语言,用户编程就在终端前定义过程命令,并利用系统提供的命令构成程序。LOGO的数据是数、字、表。由于它能方便地处理符号表,可以利用人工智能成果开发情报检索、演绎推理、自然语言会话小程序。青少年可设计各种智能游戏。屏幕上的海龟使青少年直观地构造各种图形。递归程序的表达能力使青少年可受到自动程序良好训练。1979年MIT LOGO小组推出Apple LOGO,及TI LOGO(德州仪器公司TI 99/4A机)。这两个版本最为普及。LOGO是青少年入门的启蒙语言。

            LOGO的近于自然语言的命令及海龟、键盘、程序、图形并用的使用风格,对以后的命令式语言、用户界面语言有一定的影响。

           1967年挪威计算机科学家O.J. DahI等人研制出通用模拟语言SIMULA67。它以ALGOL 60为基础,为分层模拟离散事件提出了类(Class)的概念。类将数据和其上的操作集为一体,定义出类似类型的样板。以实例进入运算。这是抽象数据类型及对象的先声。

           60年代软件发展史上出了所谓的“软件危机”。事情是由1962年美国金星探测卫星“水手二号”发射失败引起的。经多方测试在“水手一号”发射不出错的程序在“水手二号”出了问题。软件无法通过测试证明它是正确的。于是,许多计算机科学家转入对程序正确性证明的研究。这时,著名的荷兰科学家E. Dijkstra提出的“goto语句是有害的”著名论断,引起了一场大争论。从程序结构角度而言,滥用goto语句会使程序无法分析、难于测试、不易修改。这时也提出了全程变量带来的数据耦合效应、函数调用的副作用、类型隐含声明和自动转换所带来的难于控制的潜伏不安全因素等等过程语言中的一些致命性弱点。60年代对大型系统软件的需求大为增长(如编制较完善操作系统、大型军用系统),要求使用高级语言以解决生产率之需,加上高级语言使用以来积累的经验,加深了人们对软件本质、程序语言的理解。人们积极研制反映新理论的语言。

           1964年,ALGOL工作组成员N. Wirth改进了ALGO 60,提出结构化的语言ALGOL W。由于它结构简洁、完美。ALGOL W成为软件教程中示例语言。1968年,他带着ALGOL W参加新一代ALGOL的研究委员会,即开发ALGOL 68的工作组。

           ALGOL 68追求的目标也是能在多个领域使用的大型通用语言。1965年以Wijngaarden为首的一批科学家开始研究新ALGOL。强调了语言设计中冗余性(少作隐含约定)、抽象性(数据抽象与控制抽象)、正交性(一个语言机制只在一处定义并与其它机制无关)。强化了类型定义和显式转换; 有并发、异常处理功能; 保留goto允许有限制的函数边界效应: 过程可以作为参数传递; 用户可定义较复杂数据结构、定义运算符。语法定义是半英语半形式化的。语言作成可扩充式,也就是说,有一个相对完备的小语言核心,可以不断增加新特征以增强语言表达能力。表达式采用利于快速编译和提高目标码效率的逆波兰表示法。ALGOL 68集中了当时语言和软件技术之大成。但因学究气太重,一般程序员难于掌握。强调语言简单的人持有不同看法。但文本草案在Wijngaarden坚持下通过了。为此,Dijkstra等人发表了“少数人声明”。N.Wirth带着竞争失败的ALGOL W回去研究以后著称于世的Pascal。Pascal的研制者一开始就本着“简单、有效、可靠”的原则设计语言。1971年Pascal正式问世后取得了巨大的成功。它只限于顺序程序设计。是结构化程序设计教育示范语言。

           Pascal有完全结构化的控制结构。为了方便,除三种最基本的控制结构(顺序、if-then=else、while-do)外,又扩充了二种(do-until、for-do)。程序模块有子程序(过程和函数),分程序,可任意嵌套,因而有全程量、局部量、作用域与可见性概念。保留goto语句但不推荐使用。

          Pascal的数据类型大大丰富了,有整、实、字符、布尔等纯量类型: 有数组、记录、变体记录、串等结构类型; 增加了集合、枚举、指针类型。为用户描述复杂的数据结构乃至动态数据提供了方便。所有进入程序的数据都要显式声明、显式类型转换。并加强了编译时刻类型检查、函数的显式的值参和变量参数定义便于限制边界效应。在人们为摆脱软件危机而对结构化程序设计寄于极大希望的时代,Pascal得到很快的普及。它也是对以后程序语言有较大影响的里程碑式的语言。

     

    70年代完善的软件工程工具

     

            硬件继续降价,功能、可靠性反而进一步提高。人们对软件的要求,无论是规模、功能、还是开发效率都大为提高了。仅管Pascal得到普遍好评,但它只能描述顺序的小程序,功能太弱。在大型、并发、实时程序设计中无能为力。程序越大越要求高的抽象力、安全性、积少成多的模块拼合功能。为了对付日益加剧的新意义上的软件危机。70年代语言继续发展,在总结PL/1和ALGOL 68失败的基础上,研制大型功能齐全的语言又一次掀起高潮。

            70年代是微机大发展的时代。设计精巧的小型过程语言藉微机普及得到发展。软件市场FORTRAN、COBOL、汇编的三分天下开始缓慢地退却。结构化FORTRAN、COBOL力图在新的竞争中保全自己的地位,专用语言丛生。一旦证实它的普遍性,它就变为通用语言。C就是在这种情况下成长起来的优秀语言。

            硬件的完善使得过去难以实施的组合爆炸算法得以缓解。人工智能的专家系统进入实用。LISP发展为INTEL LISP和MAC LISP两大分支,其他智能语言陆续推出。特别是Backus在1978年发表“程序设计能从冯·诺依曼风格中解放出来吗?”一文。非过程式语言、高抽象模式语言大量涌现。

            70年代继60年代的形式语言语法研究,形式语义取得重大成果。最先是IBM维也纳实验室集合欧洲著名的计算机科学家于1972年写出PL/1的操作语义。该语义用维也纳定义语言VDL表达,长达1500页,终因抽象层次太低,而此时(1971年)牛津大学D.Scott和C.Strachey提出了更加数学化的指称语义学,维也纳实验室转而研究PL/1的指称语义描述。1973-1978年D. Bjorner和C. Jones开发了维也纳开发方法VDM。所用语言是Meta IV。虽然巨大投资(3.5亿)未见可见效益,IBM终止了维也纳实验室的语义学研究方向,但VDM方法及指称语言学对计算机语言发展影响是深远的。1973年C.Hoare和Wirth用指称语义写Pascal语义发现了Pascal的设计上的许多问题竟做不下去。VDM以后还用于多种语言如CHILL,Ada,指导编译器的开发。

           1971-72年,DEC公司和卡内基﹒梅隆大学的Wulf合作,开发了PDP(以后是VAX)上的系统程序设计语言Bliss。它是无类型的结构化语言,没有goto语句。有异常处理和汇编接口,面向表达式。直到80年代末DEC公司还用它作系统设计。

            1972年AT&T公司贝尔实验室Ritchie开发了C语言。C语言的原型是1969年Richard开发的系统程序设计语BCPL。K.Thompson将BCPL改造成B语言,用于重写UNIX多用户操作系统。在PDP-11机的UNIX第五版时用的是将B改造后的C。C扩充了类型(B是无类型的)。1973年UNIX第五版90%左右的源程序是用C写的。它使UNIX成为世界上第一个易于移植的操作系统。UNIX以后发展成为良好的程序设计环境,反过来又促进了C的普及。

           C语言是个小语言,追求程序简洁,编译运行效率高。是一个表达能力很强的、顺序的、结构化程序设计语言。它给程序员较大的自由度,下层数据转换灵活。程序正确性完全由程序员负责。上层是结构化的控制结构,有类似Pascal的数据类型。它的分别编译机制使它可构成大程序。输入/出依赖UNIX,使语言简短。语言学家极力反对的goto语句、无控制指针、函数边界效应、类型灵活转换、全程量这些不安全的根源C全部具备。在某种意义下C得益于灵活的指针、函数副作用和数据类型灵活的解释。易读性又不好,偏偏程序员都喜爱它。因为它简洁,近于硬件,代码高效,并有大量环境工具支持。C程序写起来又短,调试起来又快。微机上的各种移植版本的C语言,对C成为通用的程序设计语言起到了推波助澜的作用。C语言正以席卷系统程序设计领域的势头发展,并向应用领域扩展。以后的发展把与它同期出现的Pascal远远抛在后面,成为系统软件的主导语言。

           1972年法国Marseille大学的P.Roussel研制出非过程的Prolog语言。Prolog有着完全崭新的程序设计风格,它只需要程序员声明“事实”“规则”。事实和规则都以一阶谓词的形式表示。Prolog规则的执行是靠该系统内部的推理机,而推理机按一定的次序执行。在这个意义上它又有点过程性。以回溯查找匹配,Prolog的数据结构类似Pascal的记录或LISP的表。它是以子句为基础的小语言,最初被解释执行,编译Prolog是很久以后的事,由于Prolog是以逻辑推理作为模型的语言,它可以直接映射客观世界事物间逻辑关系。在人工智能研究中得到了广泛的应用,80年代日本声称研制的五代机以Prolog作为主导语言并研制Prolog机。

            70年代,在传统语言中出现了以下有代表性的语言:

           为了开发大型可维护程序,施乐公司1972-74年由Geschke领导研制了Mesa语言。Mesa是强类型结构化语言,有模块(若干子程序集合)概念和抽象数据类型。支持并发程序设计,由监控器协调各模块执行。有分别编译,异常处理机制。保留goto语句,也可以抑制类型检查。Mesa可配置语言编译后的各模块。

           1974年MIT的Liskov和Zilles提出CLU语言,它突出的是数据抽象。数据抽象是70年代类型强化和抽象技术的重要成果,它允许用户定义抽象的数据类型。这些类型的定义和它的实现可显式地分开。定义描述了语义,实现对于使用该数据的用户是无关紧要的,因而,利于修改。增强模块性和独立性,从而易于保证程序正确。数据抽象可定义更远离机器而近于人类的数据概念。如堆栈就可定义为抽象数据类型。人们可通过压入数据、弹出数据的操作对栈体进行操作。其外在行为就是后进先出的数据栈,而栈体可由数组、或链表、或记录任一种数据结构实现。

           CLU的抽象数据类型称之为簇(Cluster)。由构造算子(Constructor按簇的样板建立运算对象(实例)。CLU无goto,无全程量概念。用户可定义新的迭代(通过迭代算子Iterator)。

           数据抽象在1975年卡内基﹒梅降大学Wulf和Shaw开发的ALPHARD语言中是数据模型FORM。ALPHARD的特点是支持程序的验证。程序设计和验证同时进行。

           另一个支持程序验证的语言是加州大学Poperk和加拿大的Horning于1976年到77年开发的EUCLID。为了易于验证,无goto语句,指针仅限于集合类型,类型兼容有严格的定义,函数调用绝无边界效应。编译自动生成验证用的断言。EUCLID以后发展成数据流语言。

           在并发程序方面,1975年丹麦学者B.Hanson开发了并发Pascal。它没有追求大而全,只是将Pascal向并发方面作了扩充,希望用Pascal写操作系统。有抽象数据类型的类(Class)机制。控制方面提出进程类和管程类的概念。通过init语句激活类实例,cycle语句使进程无限循环地运行。通过管程(管理资源的模块)实现进程通讯。有较强的静态类型检查,可查出静态“死锁”。

           令人不解的是正当人们对进程、管理概念充分评价时,B.Hanson本人放弃了这些概念。1981年发表了小型系统程序设计语言Edison,仅用并发语句控制并发进程的执行。Hanson极力推崇语言的简单性,所以Edison比并发Pascal小得多,普通(不大的)微机都可以运行。但其表达能力比C差多了。没有达到并发Pascal那样的影响。

          Pascal在结构化程序设计方面是一个示范性语言,在推行结构化程序设计教学上发挥了卓越的作用,但在工程实践上暴露出设计上的许多缺点。Pascal除了无独立模块和分别编译机制不能编大程序而外,原来它的强类型是有漏洞的。类型等价似乎是按名等价,实现是按结构等价。最后的结论它是“伪强类型”。数组定长对处理字符串很不方便,布尔表达式求值定义不严,I/O规定太死,难于写出灵活的输入/输出。声明顺序过严,无静态变量概念(局部量一旦所在局部块执行完毕就消失)都给程序设计带来不便。从小而灵活方面,它又不及C,没有位(bit)级操作,指针操作限制过死。于是Pascal的设计者1975年又开始开发Modula语言,1977年正式发布为Modula-2。

           Modula-2除了改进Pascal的上述弱点而外,最重要的是有模块结构。可分别编译的模块是用户程序的资源。系统资源也以模块形式出现。模块封装了数据和操作(过程),模块定义和模块实现显式分开。程序员在定义模块中通过移入,移出子句控制程序资源(类型、变量、过程、子模块)的使用。

           Modula-2增加了同步进程机制以支持并发程序设计,有有限的低级设施直接和系统打交道。取消goto语句、增加case语句中otherwise机制,封装的模块可作抽象数据类型设计。它是用于系统设计的强类型语言。西欧的计算机科学家对Modula-2是欢迎的,但它不巧与美国开发的Ada非常近似,与Ada竞争处于非常不利的地位。尽管它的9000句编译器具有Ada20万句编译器80%的功能,也没有取得Pascal那样的成就。

           70年代中期美国软件的最大用户美国国防部(美国软件市场约2/3经费直接或间接与它相关)深感软件费用激增并开始研究原因。研究结果表明,在硬件成本降低和可靠性提高的同时,软件费用不仅相对数,绝对数也在增加。美国军用的大量大型、实时、嵌入式系统软件开发方法落后、可靠性差。语言众多(常用400-500种,加上派生方言多达1500种)造成不可移植、难于维护,为摆脱这种新的软件危机下定决心搞统一的军用通用语言。从1975年成立高级语言工作组开始投资五亿美元,前后八年研制出Ada程序设计语言。Ada是在国际范围内投标设计的,法国的一家软件公司中标,J.Ichbian成为Ada发明人。多达1500名第一流软件专家参与了开发或评审。它反映了70年代末软件技术、软件工程水平。为了提高软件生产率和改善软件可移植性,提出开发语言的同时开发支持该语言的可移植环境(APSE)。

           Ada是强类型结构化语言。封装的程序包是程序资源构件。用户只能看到程序包规格说明中显式定义的数据(包括抽象数据类型)和操作。数据结构和操作(过程或函数)的实现在程序包体中完成。封装支持模块性和可维护性。规格说明和体的分离支持早期开发(可延迟决策)。分别编译机制可组成复杂的大型软件。

           Ada有并发、异常机制。可定义精确的数据(如浮点数小数点后任意多的位数)。有将数据对象、类型、过程参数化的类属机制。有为目标机写目标程序(机器语言的或汇编语言地)的低级设施,可对字节、字位操作。Ada的私有类型支持数据隐藏,程序包可实现数据抽象。标识符和运算符重载概念,既方便程序员又使程序好读且安全。强调大型系统可读性胜于可写性,Ada程序自成清晰的文档。

           Ada语言的开发过程完全按软件工程方式进行。严格禁止方言。美国国防部有一个严格管理Ada及其环境的机构AJPO(Ada联合规划办公室)负责Ada的确认、修改、维护、培训。从业界转向软件工程方法开发软件的意义上,Ada也称之为里程碑式语言。

           由于Ada过多强调安全性和易读性,Ada编译程序要做较多的静态检查,因而体积庞大(约20万句、512KB的微机装下了微机Ada编译就剩不下工作空间了)。程序代码较长,虽不像COBOL繁琐但要比C语言程序长60%。运行效率,特别是嵌入式实时控制应用中,通过交叉编译得到的目标机代码一时还难满足要求。环境工具发展缓慢,因为除军方外民间公司更乐于开发对所有语言通用的计算机辅助软件工程环境(CASE)。自80年代第一个语言版本,83年修改定型至今, Ada没有达到投资者预想的成就。目前已看到Ada83只反映80年代初期的软件工程技术。随着软件工程本身向集成化、可重用、面向对象方向发展,Ada已有一些不适应了。但美国军方还在全力支持,1995年Ada完成面向对象改造推出了Ada-95。增加了标签类型、类宽类型、抽象类型;放宽了访问类型;使一个静态强类型语言可以支持OO的动态束定。这种改造非常痛苦,使Ada-95语法规则增至277条,成为最庞大臃肿的语言。耐人寻味的是Ada-95很块被ANSI和ISO 接受,它成为世界上第一个有法定标准的面向对象的语言。

           70年代末到80年代初值得一提的还有FORTH语言。FORTH是典型的中级语言。它是汇编语言指令码向用户自定义方向的发展。也就是说,用户可以面向一个堆栈机器模型定义操作命令——字(word)。最低层的字是指令码,逐层向上,上层字由下层组成。因此,FORTH系统有良好的继承性。系统提供核心字、解释器字、编译字和设备字。对于简单的计算解释器字直接执行命令(字),复杂计算可将字定义编译成目标码存入堆栈供以后执行。有汇编字集合以便用户直接使用机器,要求字集合操作数值计算,引用字集合使用户可以引用系统和用以前已定义的字。FORTH程序员首先查看系统中字的字典,以它们组合成新字,进而构成程序。FORTH程序的逆波兰表示法便利于解释和编译,这对长期从事汇编编程的程序员并不生疏。FORTH把具体的机器抽象为堆栈机,既可以使程序员直接操纵机器又不涉及具体机器指令码、操作码、存储安排。而且良好的继承性使程序越编越短,在最终用户层一两个命令就完成了程序设计。它大受控制领域、要求单片、单板计算机(例如仪表工业)领域的程序员喜爱。

            FORTH是C.Moore一个人开发的语言,他于1968年在IBM 1130机器上实现第一个FORTH。他说他的语言是第四代的(Fourth-Generation)。由于1130只允许五个字符的名字才叫FORTH。1973年成立FORTH公司并把它投入航天工程应用,发展了通用商务FORTH系统。此后世界各地开始重视FORTH。1976年成立欧洲FORTH用户小组(EFUG),1978年成立FORTH标准化国际组织,80年发布FORTH-79标准文本。与此同时美国FORTH爱好者小组FIG)也制定了标准fig FORTH。各国天文行业,仪表行业纷纷以其为行业用计算机语言。FORTH并不好读,也不宜编大程序。但在它自己的领域简单好用、扩充方便、编译迅速。与传统语言追求的目标大相径庭。给人耳目一新。


    80年代的面向对象发展

     

           Ada的大、功能齐全、开发耗资可以说是程序设计语言之最。但它还没有普及就有些落伍了。可能今后不再有人再投入巨资去开发大型过程语言。

           80年代继续向软件危机开战,但软件工程以陈旧技术难于作出庞杂的软件工具。为了改善这种情况,人们乞灵于面向对象技术。程序设计语言纷纷面向对象靠拢。正如上一个10年程序设计语言结构化一样。这是主要特点。

           80年代的第二个特点是“用户友好”的所谓第四代语言的出现。

           80年代的第三个特点是各种技术相互渗透各种更高级非过程性语言出现。

          1972年美国施乐公司保罗·奥特研究中心的A.Kay领导的软件概念小组为方便不同用户处理各种信息在小机器上搞了一个Dynabook计划。它以全部的“对象”概念建立自己的系统。1980年Smalltalk-80作为正式的发布版本。

           Smalltalk语言是该系统的软件。专用的硬件机、Smalltalk环境、用户界面、面向对象程序设计风格构成了整个系统。

         “对象”是有自己的数据和操作的实体,各对象相对封闭。程序设计就是建立应用系统中的对象群,并使之相互发消息。接到消息的对象就在自己封闭的存储中响应执行操作。操作的结果是改变这组对象的状态、完成计算(发出输出消息,对象响应后完成输出)。

           为了使各自封闭的对象数据和操作不致多次重复定义。Smalltalk有类和继承的概念。类如同传统语言中的类型,只有类的实例进入实际运算(叫实例对象)。类对象中的数据和操作可为它的子类继承,它自己的数据和操作也继承自超类。于是一个Smalltalk系统就必须有支持它的一个类库,它象一棵大树,所有的行之有效类都在这棵大树的某个位置上。用户只要选取其中某些类稍加修改变成自己问题所需要的类(子类),定出通讯协议,让它们的实例相互通讯完成计算。无论是系统对象和用户定义的对象都按不同的抽象层次放在统一的类库中。例如,向编译对象发消息并传送用户对象,该用户对象(程序)就被编译了。Smalltalk中只有不同抽象层次的对象,小到一个整数、大到一个系统都叫对象,且别无其它计算单元。面向对象程序设计的概念因此而出。

           Smalltalk因为它天然的封装性体现了模块性和数据隐藏,利于维护修改。它的继承性实质上是软件的重用。这对困惑于大程序难于管理的软件工程学无疑是一条绝好出路。

           Smalltalk类对象概念来自SIMULA 67,响应消息的方法表达式求值类似LISP的归约。它本身是在小机器上开发的小系统。庞大的类库占去了很大的空间,难于编制大型程序。加上它独特的编程风格,Smalltalk本身并未发展起来。但面向对象思想,语言和环境一致性; 交互式和极端用户友好(用菜单和鼠标即可上机),对80年代语言和计算系统产生了巨大影响。它也可称之里程碑式的语言。

            各种过程语言,甚至汇编语言都借鉴对象思想,以求能支持面向对象程序设计。82-86年相继出现Object Pascal、Objective-C、Objext Assembler(68000汇编程序改造)。Object、LOGO、Object FROTH它们以原有语言采纳对象——消息编程模式。

           另一些语言向类、对象延伸。以对象——引用编程模式编程。如85年AT&T公司推出的C++。87年Borland公司的Turbo Pascal 5.5。

           传统的人工智能语言也向面向对象上发展。施乐公司1983年在Intel LISP基础上研制了LOOPS。是面向对象LISP美国西海岸版本。85年美国符号处理公司在MIT的LISP机上开发了Flavos,称之为东海岸版本。Flavos有更为灵活和复杂的多继承性。85年施乐公司又作出Common LOOPS。1988年,ANSI X3J13组将它们统一为CLOS。85年,IBM日本分公司开发了SPOOL是Prolog面向对象的扩充。86年Valcan和施乐联合开发的并发Prolog预处理程序,也是支持面向对象的。


           70年代在软件发展史上是数据库成熟的年代。数据库有数据描述语言DDL数据操作语言DML。它们都是为实现某种模式数据库的专用语言。目标简单,在所应用的领域高效。因此,不能以通用程序设计语言代替。数据库给用户以界面(即查询)语言。对于简单程序没有必要转到通用语言再编程序。查询语言进一步扩充,就形成一系列查询命令加上约束条件控制的非过程语言。如SQL。1988年SQL成为正式ANSI/ISO标准。

           80年代软件环境大发展。操作系统原有的作业控制语言(JCL)和系统调用命令也逐步发展为该环境的统一的界面语言。如UNIX的Shell。

           80年代系统软件中开发环境的思想向各专业渗透。各专业都为本专业的最终用户提供简便的开发环境。即事先将程序模块以目标码存放计算机,用户只需简单的命令,甚至本专业常用的图形就可组成应用程序。这些图形、菜单、命令即用户界面语言。

            这些语言共同的特点是声明性(只需指明要做的事)、非过程性、简单、用户友好。而应用程序的实现可由系统自己完成(低层有固定不变的计算模型,如关系运算,也可以连接备用模块智能推理)。这就所谓的第四代语言(4GL)。

           4GL并没有为程序设计语言学带来什么新概念和新特征。一般用传统技术做出界面语言解释器。要求环境有较好的工具支持(应用程序、程序库、各种测试、调试、文档工具)。最简单的4GL是图形——菜单,用户不用击键即可完成计算(用鼠标器)。

           4GL是硬件高速发展和快速降价必然的结果。因为不可能在短期内培养出与硬件发展需要出匹配的那么多的程序员。但4GL不易编制开创性程序。

    九十年代网络计算语言

           九十年代计算机硬件发展速度依然不减。每片芯片上晶体管数目仍然是一年半增加一倍。计算机主频从12-25兆赫增加到500-600兆赫(每秒钟可执行750MIPS指令),价格进一步低廉。使用方式也从多人一机的分时系统到一人一机局域网计算,到每人都成为拥有全球资源的客户。建立在异质网上的多媒体环境已成为客户端使用环境的主流。支持“所见即所得”的用户界面的“语言”大量涌现。

           ·由于有良好环境支持,程序设计重点从算法加数据结构实现技术向规模说明描述方面转移。规模说明语言在80年代已有研究。(META-IV,EPROL,HOPE,CLEAR、SPECINT,Z)在个别具体领域也能实用。但作为通用,哪怕是某个行业建立在域分析基础上的规格说明语言尚未出现。

           ·环境智能化、规模说明语言自动生成目标码客观上要求加入人工智能技术。异质网环境推行后各结点上数据库资源共享都要求各语言间不要有人为的断层。因此,多范型语言研究会有较大发展。80年代向面向对象扩充已经出现多范型语言,如C++,Ada 95(命令式加对象式)、CLOS(函数式加对象式0。为外小型研究有TABLOG(关系式加逻辑式)、Funlog(函数式加逻辑式)值得注意的是加拿大的Nial(1983-88)和美国的G(1986)语言,它们试图将五种范型: 命令式+对象式+逻辑式+函数式+关系式统一在一个语言之中。虽然问题重重,但可由此发现许多新概念和新特征,对于程序设计语言研究是非常有利的。

           ·随着面向对象数据库和面向对象操作系统的成熟,完全消灭“语义断层”的数据库程序设计语言(DBPL)和持久性程序设计语言(PPL)终将汇合并标准化。这样,程序运行时大量文件到内存转换则可以取消,从而增大了计算机的实崐时性,甚至取消文件概念。

           ·4GL有了较大发展,种类花色增多,行业标准出现。支持它们的通用程序设计语言是C、C++、Ada。

     

    2010-01-20                  

    注:源自原百度博客“至美心"

    展开全文
  • 对面向对象程序设计(OOP)的认识

    千次阅读 2013-07-29 19:21:53
    前言  本文主要介绍面向对象(OO)程序...它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。  简略来说,面向对象程序设计,指采用了面向对象的方法来进行程序设计。设计

    前言

      本文主要介绍面向对象(OO)程序设计,以维基百科的解释:面向对象程序设计英语Object-oriented programming,缩写:OOP),指一种程序设计范型,同时也是一种程序开发的方法。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。

      简略来说,面向对象程序设计,指采用了面向对象的方法来进行程序设计。设计指一种把计划、规划、设想通过视觉传达出来的活动过程,它是一种创造性,积累性,实践性的工作。提笔写设计的文章是很有压力的,它不像深入一个知识点一样让人容易有的放矢,一千个读者心中有一千个哈姆雷特,同样的项目两个人来做架构肯定不一样。包括我,每几年对设计都会有一些不同的看法,回头来看自己的代码也总会挑出很多不足,世界是不完美的,设计却希望尽求完美,闲话不说,来进入本文的正题,看看从何谈起。

    面向过程程序设计

      面向过程程序设计不是面向对象程序设计的前提,从面向过程谈起主要是因为自面向对象(OO)程序设计一提出,就有太多的两者对比。在这样的对比中,面向过程被形容成老化,腐朽,僵硬的设计模式,它自上而下,按照功能逐渐细化,实现快速但面对变化时束手无策。相对而言面向对象具有封装性,重用性,扩展性等一系列优点,言而总之:“还面向过程??你out了,来面向对象吧。。。”

      C语言是面向过程的代表,它在1972年由贝尔实验室的D.M.Ritchie提出,在Unix系统中大放异彩,直至今天在系统软件,图形动画,嵌入开发等众多领域中还保持着旺盛的生命力。程序设计这个概念,伴随着程序开发被提出,最简略的被描述为 程序设计=数据结构+算法,通俗一点的说程序设计指的是设计、编制、调试程序的方法和过程。人是善于思考总结的,在漫长的面向过程的程序开发中,一些设计原则被提出,用以更好的指导设计:

    1. 模块原则:使用简单的接口拼合简单的部件。
    2. 清晰原则:清晰胜于技巧。
    3. 组合原则:设计时考虑拼接组合。
    4. 分离原则:策略同机制分离,接口同引擎分离。
    5. 简洁原则:设计要简洁,复杂度能低则低。
    6. 透明性原则:设计要可见,以便审查和调试。
    7. 健壮原则:健壮源于透明和简洁。
    8. 优化原则:雕琢之前先要有原型,跑之前先学会走,不要过早优化。
    9. 扩展原则:设计着眼于未来,未来总比预想快。

      以上原则参考自《Unix编程艺术》,书中总结了17种原则来指导程序设计,精简为一句话就是Unix哲学“KISS—Keep It Simple, Stupid!”,保持简单。

      KISS,Keep Simple,Keep是它的核心词,底层的API设计,可以尽量保持简洁清晰,外部的需求变化,Keep?你Hold得住么?

    需求变化,你Hold得住么?

      你Hold不住!

      变化来源于对事物认识的发展和外部业务的变更,当然实际中变化可能来自于更多方面。你不能拒绝变化,你只能拥抱变化,在长期的程序设计中,两条设计原则被提出:

    1. 简洁,用更长的三个词来说应该是简洁,清晰,透明。程序应该易于读懂,易于维护,最好有文档注释。世界在变,规则在变,今天精巧的设计,可能成为明天修改的沉重包袱。
    2. 重构,在不改变软件现有的功能上,通过调整程序代码而改善软件质量,性能等。面向过程中重构的原则性目标在于提高正交性,所谓正交性,是指任何操作均无副作用,每一个动作只改变一件事,不会影响其它。具体到API设计就是一个API中不应做两件事,一个粗粒度内部做几种事情的接口可以细化为多个细粒度的接口,“只做好一件事”,这个忠告不仅是针对简单性的建议,对正交性也是同等程度的强调。

      按照正交性的设想,我们应该打造一个纯正交的系统,在这个设计中,任何操作均无副作用,每一个动作只改变一件事不会影响其它,改变一件事情一个具体方面的方法只有一个。想法是完美的,世界是复杂的,软件要能做到拥抱变化,设计希望达到高内聚(模块内元素紧密结合),低耦合(模块间依赖尽可能低),那么如何来拥抱变化呢?

    让它“活”起来

      程序最有魅力的事情在于创造,程序员使用代码来完成程序的创造。一花一世界,一木一浮生,作为粘土世界的上帝,我们采取了很多的努力来完成我们的设计:

    1. 分清程序中可变和不可变的部分,相对来说,数据是不可变的,算法是可变的,我们设计好相对稳定的数据,再细化算法,应对变更。
    2. 以模块化来划分程序,按功能来划分模块,这样从纵向看,程序是由一个个的模块组成的,从横向看,我们定义好模块间通信的接口,程序就是由模块组织起来的联合体。

      程序像流水线一样工作起来了,数据从上到下开始运作,但是变化仍然无处不在,大修小补依然无法避免。如果模块设计的足够独立,程序的正交性足够好,变动还在可控范围之内。一旦变化跨越多个模块,程序经过多次大修,就会有种想把它捏回泥巴的冲动。

      外部的变化还在继续,里面依旧是勤恳,冰冷的泥块,怎么来拥抱变化?对,伸出你的金手指,让它“活”起来。

    对象

      英雄应运而生,对象应责而生。我们点“活”了对象,就是为了让它解决事情承担责任。从:

       1: struct Data
       2: {
       3:     int d;
       4: };
       5: void increase_data(Data* data)
       6: {
       7:     printf("过程调用,数据为: %d", ++data->d);
       8: }
       9: increase_data(&Data());

      到

       1: public class DataWorker
       2: {
       3:     private int data;
       4:     public void Increase()
       5:     {
       6:         Console.WriteLine("对象调用,数据为: {0}", ++data);
       7:     }
       8: }
       9: new DataWorker().Increase();

      把传统的数据和处理数据的函数封装起来,用DataWorker对象来表示,数据变成了对象的状态,函数变成了对象的方法(行为)。一个对象被我们点“活”了,它负责处理一件事情,把责任下放是点活对象的出发点--“变化太快了,面面俱到的管理让我疲于奔命,你就负责处理这块事情吧,由你来应对这块事情的变化”。

    替换

      对象被我们点活了,它们各尽其责来处理自己的事情,程序处理被变成了一个个对象间的相互协作,如果有变化产生我们找到负责的对象,由它来处理变化。想法是完美的,可是具体到对象,它怎么来应对变化?修改自己的方法(行为)?

      对象是我们点活的,责任是我们分配的,方法(行为)是我们指定的,发生变化了还要我们来修改它的方法(行为),那绕一圈点活它干嘛?和面向过程中直接修改对应的函数有啥区别?是的,可能方便在于比较容易定位到它,但是你修改了一个对象后,如何保证和它协作的别的对象没有意见,不会造反?

      从现实来讲,作为一个老总,指派了一个区域经理来负责一块业务,负责的业务出现了问题,你会对它的业务指手画脚来重新教育他该怎么做么?不会的,不要让自己陷入泥潭,首先信任,不行就炒了他,换一个。

      应对变化的关键点在于替换,这样才不会使自己陷入细节。替,顶替,表示新对象可以承担旧对象的职责,对协作的别的对象没有影响。换,表示要能应对变化,更改处理责任的具体方法(行为)。这是一个共性和变性的描述,那么怎么用程序语言来表示?

      类是面向对象程序语言中的一个概念,表示具有相同行为对象的模板,类声明了对象的行为,它描述了该类对象能够做什么以及如何做的方法。一个类的不同对象具有相同的成员(属性、方法等),用类来表示对象的共性,那么怎么来表示变性呢?

      类之间支持继承,可以用父类和子类来表示这层关系,用自然语言来形容,父类是子类一种更高程度的抽象,比如动物和哺乳动物。子类可以添加新的行为或者重新定义父类的行为来完成变化。允许子类来重定义父类的行为,在对象间的相互协作中尤为重要,可以把不同的子类对象都当做父类对象来看,这样可以屏蔽不同子类对象间的差异。在需求变化时,通过子类对象的替换来在不改变对象协作关系的情况下完成变化,这种特性也被称为多态。

      封装,继承,多态,被称为面向对象技术中的三大机制,那么回到本文的主题,什么叫面向对象呢?

    面向对象

      所谓面向对象,面向两个字很重要--“我的眼里只有你”,面向对象的哲学在于把软件(世界)看成是由各种各样具有特定职责的对象所组成,不同对象之间的相互作用和通讯构成了整个软件(世界)。以面向对象的角度去进行程序设计,需要至少以下三步:

    1. 发现(设计)对象;
    2. 确定对象的职责;
    3. 确定对象间的相互关系。

      按前面所提,类是具有相同行为对象的模板,通过同一个类创建的不同对象具有相同的行为,对象是类的一个具体例子(实例),我们面向对象设计程序时,一般从类的设计开始。

    类的设计

      类通常情况下是自然世界中一个概念的描述,比方说Person类通常对应人,这种软件和自然世界中的对应关系使我们可以尽可能运用人类的自然思维方式去解决问题。那么如何发现类呢?一个最简单的办法就是把我们熟知的自然概念直接抽象为类,比方说一个图书馆借书的程序,管理员,书,借书者,我们可以很容易想出一系列的概念,这些名词概念来自于我们对生活对该领域的了解。把我们熟悉的名词(概念)直接抽象为类,把动词抽象为该类的行为,这是一种最粗糙的类设计方法。这种设计比较容易下手,但是也会出现一些问题:

    1. 实现性,事物分抽象事物和具体事物两种,程序设计中用类的实例(对象)来表示一个具体事物。对于人来说,管理员,借书者都是人,同一个人可以充当不同角色,一个人可以通过学习具备一些能力并且通过经验积累来优化自己的能力。那么如何来设计这样一个类,让该类可以具备责任并自适应变化?
    2. 目的性,现实世界中,解决一个领域的软件总会遇见各种各样的概念,那么需要把这些概念全部抽象为类么?面向对象就是把所有概念全部类化?

      对第一点来说,这是一个理想状态,大多数面向对象语言都是静态语言,如C#/Java/C++等,类作为对象的模板,既确定了该类对象的功能,在编译后又决定了对象的内存模型。静态语言使用继承,接口来完成类的扩展,相比动态语言,静态语言在运行速度,类型安全上有着很大优势,但由于类的扩展性是在编译期决定的,要应对变化就需要在类的设计上多下功夫。

      针对第二点,这个前面已经提到了,引入对象的唯一原因是具有责任,应对变化,让它“活”起来,是为了让我们更轻松的生活,面向对象是一种方法观,程序执行后仍然被编译成一条条的过程语句执行。不要舍本逐末,来总结一下面向对象的设计经验。

    设计模式

      设计模式,这里的全称应该是面向对象设计模式,我们熟知的设计模式,通常指GOF定义的23种设计模式。每种模式都有一个对应的名字,按种类可分为创建型,结构型和行为型三类。

      介绍面向对象设计模式的文章也很多,模式,按Alexander的经典定义,指在某一背景下某个问题的一种解决方案。这里的解决方案指细节,某一背景下某个问题才是难点,深刻理解“什么时候,什么场合用”比“如何用”更重要,既然是面向对象设计模式,先从对象创建说起。

      面向对象是为了适应变化,变化无处不在:

    1. 对象的创建要能适应变化,它不会自己凭空跳出来,必须有其他对象来负责该对象的创建。通常用工厂对象(Factory)来负责对象的创建,在工厂的基类中定义创建对象的虚方法,由工厂的子类来具体化这个创建。
    2. 对象间的组织结构要能适应变化,如一般大公司具有总经理-部门经理-项目经理-员工等职位,完成一件事情需要各部门各员工间的配合,混乱的组织结构会导致难以应对扩张,对象间职位不清等问题。
    3. 对象的行为要能适应变化,为了完成责任,变化可能来自于各个方面,可能会受对象状态的影响,可能需要其他对象的协助等等。

      设计模式是一种经验的积累,面向对象设计模式的根本是为了应对对象变化,每种设计模式都对应了一类变化点。这就需要在实际运用中识别变化点,因地制宜的分析可否引入对应的设计模式来最佳化设计。

    后记

      文章存在草稿里很久了,再接已经没有思路了,简略了描述一下后面的想法:

    1. 关于面向对象设计的方法:面向对象程序设计仍在发展之中,关于如何指导用户从面向对象角度分析和设计程序,四色原型分析方法,领域驱动建模思想,DCI架构等都是一些好的经验。当然,这些经验都是帮助我们更好的去设计程序的,要因地制宜,不要本末倒置,不看实际就选定了一种方法,再生搬硬套把需求塞进这些框框之中。
    2. 关于面向对象设计的优点:前面列举了面向过程的一些好的经验(模块原则,组合原则,扩展原则等),是因为在很多介绍面向对象程序设计的文章中,往往夸大了面向对象设计的优点。这些好的思想原则是通用的,不仅仅是面向对象设计所独有的。面向对象程序设计的优点在于它契合了人们分析自然时概念化的思维方式,在解决真实生活问题时往往比较容易下手。
    3. 关于面向对象设计的缺点:成也萧何败也萧何,如果我们正确分析了需求,找准了可能的变化点,设计出的类模型往往具有较高的价值。如果错误的假设了程序的逻辑,过细/忽略了可能的变化点,则设计出的程序可能会导致结构混乱,抽象过多/无法扩展等问题。面向对象程序设计多呼吁尽早的引入领域专家帮助分析建模,来防止错误的捏造对象导致事倍功半。
    4. 关于面向对象设计的实践:变化是不断存在的,很难存在所谓的完美设计,即使有领域专家的帮助,也很难做到类完全对修改封闭,对扩展开放。随着开发的深入,重构是不可避免的,这里重构的作用既要适应变化,又要保证已有功能的正确性。关于这方面的实践,敏捷是比较热的词汇,敏捷的主张在于用简单的初始设计,然后小步的持续改进,通过TDD来确保每一步改进的正确性。要应对变化,就要预知变化,设计抽象来隔离变化,当然,过度的抽象也会增加软件的复杂度,一个简单的指导原则是,在不能预知变化或者变化不是十分剧烈前,不要过多设计,清晰胜于一切。
    5. 关于面向对象设计和编程语言:众所周知,C++/JAVA/C#等是面向对象的语言,在语言层次提供了类的支持,但并不是这些面向对象语言写出来的一定是面向对象的程序,比如所谓的充血/贫血模型---对象的行为是否被封装在对象其中,还是由Service来提供。这里出现了很多的名字,DomainObject,ValueObject等等,抛去这些名字不谈,如果对象的行为由对象来提供,那么这个对象才真正“活”起来,否则它还是过程化的数据封装。但并不是这样做不好,面向对象设计不是万能药,错误点“活”了对象,不仅不会让你省心,还会让你更加操心。反过来C语言等面向过程语言也可以支持面向对象的思想,Windows的WNDCLASS就是一个很好的例子,换一个角度去讲,如果程序中出现了依赖倒置,依赖于抽象而不依赖于具体,这种抽象体现出来的就是面向对象的思想。

    题外话

      设计方面的话题总是显得空泛,设计能力的提升来自于经验,脱离了实际去谈设计模式无疑纸上谈兵。设计上面对应需求,下面对应编码,实际又为项目服务,受项目资源制约。好的设计来自于坚持和妥协,也许往大了说很多东西也如此,祝朋友们多点积累,少点折腾,谢谢。

    展开全文
  • 结构化方法的基本思想就是将待解决的问题看作一个系统从而用系统科学的思想方法来分析解决问题结构化方法遵循以下基本原则 (1)抽象原则 抽象原则是一切系统科学方法都必须遵循的基本原则它注重把握系统的...
  • 1.1 程序设计语言发展的四个阶段  到目前为止,程序设计语言的发展经过了机器语言、汇编语言、高级语言、第四代语言四个阶段,每一个阶段都使程序设计的效率大大提高。我们常常把机器语言称为第一代程序设计语言,...
  • 面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是一种计算机编程架构。OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。OOP 达到了软件工程的三个主要目标:...
  • 微信的小程序和小游戏的区别

    万次阅读 2018-06-13 15:09:39
    小游戏是小程序的一个类目,小游戏是微信开放给小程序的更多的能力,让小程序开发者有了开发游戏的能力。...小游戏在小程序环境的基础上提供了 WebGL 接口的封装,使得渲染能力性能有了大幅度...
  • 面向对象程序设计

    千次阅读 2011-10-23 22:26:22
    面向对象程序设计 求助编辑百科名片 面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是一种计算机编程架构。OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象...
  • Java职业发展和成长路径

    千次阅读 2019-08-01 23:23:14
    Java职业发展和成长路径(所需技能) 一、JAVA程序员 1. Java开发入门: Java开发环境的安装与使用,包括JDK命令、EclipselDE、 Linux 下Java程序的开发部署等。 2.Java语法基础:基于JDKEclipse环境,进行...
  •     数据库技术是应数据管理任务...    在应用需求的推动下,在计算机硬件、软件发展的基础上,数据管理技术经历了人工管理、文件系统、数据库系统三个阶段。 数据管理三个阶段比较 人工...
  • 对C++面向对象的编程的理解

    千次阅读 2019-01-16 18:05:06
    面向对象方法历经了30多年的研究和发展,已经日益成熟完善,应用也越来越深入广泛,现其已经发展为主流的软件开发方法。 本节主要介绍面向对象方法的优点以及它的一些基本概念。 2.3.1面向对象方法的优点(1)与...
  • 学习Java的你,真的会面向对象编程吗?

    千次阅读 多人点赞 2020-07-19 15:23:30
    学习Java的你,真的会面向对象编程吗?本文主要讲解什么是面向对象,以及如何在Java中实现面向对象编程,欢迎您前来学习!
  •  优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。   缺点:没有面向对象易维护、易复用、易...
  • Java面向对象总结篇

    千次阅读 多人点赞 2019-01-17 15:48:33
    面向对象在百度百科中是这样解释的:“面向对象是一种对现实世界理解抽象的方法,是计算机编程技术发展到一定阶段后的产物”。说的好像很流弊的样子,看看就行。 说道面向对象,大家肯定会想到面向对象的三大基本...
  • 编译原理的地位 是软件技术的基础 是计算机专业的基础课程,是专业必修课 编译原理的作用 编译原理是介绍如何将高级语言程序变换成低级语言程序的方法。...ADA 对象式语言:Java, C++ 等 函数式语
  • 面向结构面向对象区别

    千次阅读 2013-03-29 22:30:00
    面向对象与面向过程的区别 1、面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使 用的时候一个一个依次调用就可以了。 面向对象是把构成问题事务分解成各个对象, 建立对象的目的不是...
  • 在传统的软件开发过程中多采用结构化技术完成软件开发的一系列工作,但这种方法并不适应发型软件产品的开发,而随着硬件发展,对于大型软件产品的需求又逐步提高,于是面向对象方法就应运而生。面向对象方法在上世纪...
  • 因为想在笔记中夹杂这篇文章中部分内容,所以进行了还是比较多的引用,核心的地方还是自己写的 可以一直接调转到深入理解Java的OOP ...名称:Object-Oriented Analysis:面向对象分析方法 OOA是指...
  • 程序的启动退出过程详解

    千次阅读 2015-03-06 11:09:44
    Windows支持两种类型的应用程序。一种是基于图形用户界面(GUI)的应用程序,另一种是基于控制台用户界面(CUI)的应用程序。...Wi n d o w s 配备的所有应用程序附件(如Notepad 、Calculator WordPad ),
  • 万字长文深度剖析面向对象的javascript

    万次阅读 热门讨论 2020-12-02 09:46:56
    本将会深入讲解面向对象在javascript中的应用,并详细介绍三种对象的生成方式:构造函数,原型链,类。
  • 面向对象分析与设计——对象模型

    千次阅读 2014-10-22 09:18:58
     对象模型包括:抽象、封装、模块化、层次结构、类型、并发持久   2.1 对象模型的演进   OO建立在以前技术的最佳思想之上。两大趋势:小规模→大规模;高级程序设计语言;   2.1.1 程序设计语言的换代...
  • 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,...面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行
  • 程序设计方法学基本概念汇总

    千次阅读 2015-07-28 00:01:01
    程序设计方法学是软件工程专业必修课之一。在这门课程中会学到很多程序设计方法,以及一些优化代码的思想。是站在一个较高的层次上进行程序的架构与设计。以下的基本概念是我在大学阶段整理的资料,希望能对大家有用...
  • 入门学习Linux常用必会60个命令实例详解doc/txt

    千次下载 热门讨论 2011-06-09 00:08:45
    在使用mount这个指令时,至少要先知道下列三种信息:要加载对象的文件系统类型、要加载对象的设备名称及要将设备加载到哪个目录下。 (1)Linux可以识别的文件系统 ◆ Windows 95/98常用的FAT 32文件系统:vfat ;...
  • 程序设计者考虑的是对象的描述、 对象间的关系、类的管理、什么时候什么地方调用对象的哪一种方法。 面向对象技术的最大优点是有效支持重用 , 使得大的程序也变得相对容易维护。 2、 面积对象程序设计面向...
  • 程序设计语言的基本概念

    千次阅读 2019-01-20 16:56:37
    程序设计语言是为了书写计算机程序而人为设计的符号语言,用于对计算过程进行描述、组织推导。 程序设计语言的广泛使用始于1957年出现的FORTRAN,程序设计语言的发展是一个不断演化的过程,其根本推动力是更高的...
  • 在知乎上看到一位对这两者的一句概括“面向对象类似于纪传体,面向对象类似于编年体”,可以看看《史记》《资治通鉴》目录。 面向过程   优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较...
  • 测试开发需要学习的知识结构

    万次阅读 多人点赞 2018-04-12 10:40:58
    该技术主要的特征是测试对象进入了代码内部,根据开发人员对代码程序的熟悉程度,对有需要的部分进行在软件编码阶段,开发人员根据自己对代码的理解接触所进行的软件测试叫做白盒测试。这一阶段测试以软件开发...
  • Linux内核驱动中面向对象的基本规则实现方法 - 内核版本 Linux Kernel 2.6.34, 与 Robert.Love的《Linux Kernel Development》(第三版)所讲述的内核版本一样 - 源代码下载路径: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 136,369
精华内容 54,547
关键字:

发展对象确定的程序和要求