Java沉思录之面向对象

通过相关编程语言的发展历史,探究面向对象的思想。

面向对象发展历史

从面向过程说起

自C语言出现以来,风靡一世,操作系统、各种软件、工具使用C语言开发。更甚的是尼古拉斯·沃斯喊出的那句,“算法+数据结构=程序”。仿佛所有问题只要一步一步走下去就能解决。事实上,如果要使用面向过程的思想来处理当然也是没问题的。不过这时候,总有一个疑惑萦绕不去,这种方法是不是最优解?如果一个项目,使用面向过程的方法,新的需求出来了,是不是容易扩展?代码是否能够重用?是否容易维护?面向过程是计算机的思维,人毕竟不是机器。随着项目人数增多,代码越来越复杂,如何有一种方法来简化,面向对象就是这样的一把利器。

Simula 67 第一个面向对象语言

1967年,面向对象技术最早是在编程语言Simula 67中出现的,被认为是第一个面向对象程式设计的编程语言。它引入了所有后来面向对象程序设计语言所遵循的基础概念:对象、类、继承,但它的实现并不是很完整。Simula影响了Smalltalk以及接下来所有的面向对象设计编程语言。

Smalltalk 第一个完整实现了面向对象的语言

Alan Kay在70年代创造了 Smalltalk,被公认为历史上第二个面向对象的程序设计语言。它是世界上第一个真正把面向对象作为程序组织基础手段的编程语言。它首次明确实现了"消息"和"继承"这两个重要概念,对于"封装"和 "多态"也给出了里程碑式的解决方案。在 Smalltalk 程序中,一切程序元素(除了词法元素)都是对象,一切操作都是消息。而且,Smalltalk 的实现本身就是用 Smalltalk 写成的,这也就意味着,对于一个 Smalltalk 程序来说,它的底层也是以面向对象为基础的。Smalltalk引领了面向对象的设计思想的思潮,对其它众多的程序设计语言的产生起到了极大的推动作用。C++,C#,Objective-C,Actor,Java和Ruby等,无一不受到Smalltalk的影响。

C++ 第一个大规模使用面向对象的语言

面向对象程序设计在80年代成为了一种主导思想,这很大程度上得益于C++的流行。C++由贝尔实验室的Bjarne Strou-strup与1983年推出,C++进一步扩充和完善了C语言,成为一种面向 对象的程序设计语言。C++最开始的时候不是叫做C++,而是C with class。正是因为C++兼容C,同时又具备了面向对象的能力,所以C++至今仍旧广受欢迎。然而由于C++想要面面俱到,吸收了其他各种语言的特性,搞成了一个大杂烩。语法十分复杂,导致针对C++存在很多批评和争议。

Java是目前使用最广的面向对象语言

自Sun公司于 1995年5月由“Java之父”James Gosling推出Java以来,面向对象技术才算被推上了王座。Java至今仍旧是使用最广的面向对象编程语言,拥有全球最多的开发者。Sun公司对Java语言的解释是:“Java编程语言是个简单、面向对象、分布式、解释性、健壮、安全与系统无关、可移植、高性能、多线程和动态的语言”。所以要了解Java,面向对象是绕不过去的。对象在Java中是一等公民。

面向对象究竟为何物?

什么是对象?

那么究竟什么是对象呢?对象是相关状态和行为的软件实体。我所理解的对象其实是现实世界的客体在代码中的一个映射,或者说是一种模型。我们将客观存在进行抽象,比如一只狗,将它的大小、品种、颜色、毛长等等数据抽象为属性。将它的一些吃饭、睡觉、吠叫等行为进行抽象为方法。然后在代码世界里面就真的创造了这么一只狗对象。它具有现实世界狗的特征和动作。

什么是类?

类是创建对象的蓝图或原型,类是不占内存空间的,对象是类的实例,是需要存在内存中的。

为什么要面向对象?

面向对象是为了解决系统的可维护性,可扩展性,可重用性,面向对象的具有模块化、信息隐藏、代码重用、可扩展及易调试等优势。并且使用面向对象能够最容易地解决我们遇到的大部分问题。

面向对象的基本特征和基本原则

三大基本特征

我们从面向对象的三大特征就能体现其思想优势了。

  1. 封装: 将对象特有的属性和方法隐藏起来,不对外暴露,就可以在不影响其它部分的情况下修改或扩展被封装的变化部分,这是所有设计模式的基础,就是封装变化,因此封装的作用,就解决了程序的可扩展性。
  2. 继承: 子类继承父类,可以继承父类的方法及属性,实现了多态以及代码的重用,因此也解决了系统的重用性和扩展性,但是继承破坏了封装,因为他是对子类开放的,修改父类会导致所有子类的改变,因此继承一定程度上又破坏了系统的可扩展性,所以继承需要慎用,只有明确的IS-A关系才能使用,同时继承在在程序开发过程中重构得到的,而不是程序设计之初就使用继承,很多面向对象开发者滥用继承,结果造成后期的代码解决不了需求的变化了。因此优先使用组合,而不是继承,是面向对象开发中一个重要的经验。
  3. 多态: 为不同数据类型的实体提供统一的接口就是多态。狭义上的多态就是指父类引用指向子类对象,调用方法时会调用子类的实现,而不是父类的实现,这种是运行时多态。多态需要满足三个条件:1.要有继承关系 。2.子类要重写父类的方法。 3.父类数据类型的引用指向子类对象。这里有两个概念需要区分一下,方法重载(Overload):一个方法名,参数不同。方法覆盖(Override):父类与子类有同样的方法名和参数。多态与方法覆盖有关,与方法重载无关。广义上来讲,不同的类通过实现同一接口来实现各自的功能也算是一种多态。比如鸟会飞,但是超人也会飞,通过飞这个接口,我们可以让鸟和超人,都实现这个接口,这就实现了系统的可维护性,可扩展性。

五大基本原则

  1. 单一职责原则(Single-Resposibility Principle):一个类,最好只做一件事,只有一个引起它的变化。 单一职责原则可以看做是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。职责过多,可能引起它变化的原因就越多,这将导致职责依赖,相互之间就产生影响,从而大大损伤其内聚性和耦合度。通常意义下的单一职责,就是指只有一种单一功能,不要为类实现过多的功能点,以保证实体只有一个引起它变化的原因。
  2. 开放封闭原则(Open-Closed principle):软件实体应该是可扩展的,而不可修改的。 也就是,对扩展开放,对修改封闭的。 开放封闭原则主要体现在两个方面1、对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。2、对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对其进行任何尝试的修改。
  3. 里氏替换原则(Liskov-Substituion Principle):子类必须能够替换其基类。 这一思想体现为对继承机制的约束规范,只有子类能够替换基类时,才能保证系统在运行期内识别子类,这是保证继承复用的基础。在父类和子类的具体行为中,必须严格把握继承层次中的关系和特征,将基类替换为子类,程序的行为不会发生任何变化。同时,这一约束反过来则是不成立的,子类可以替换基类,但是基类不一定能替换子类。
  4. 依赖倒置原则(Dependecy-Inversion Principle):依赖于抽象。 具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象。我们知道,依赖一定会存在于类与类、模块与模块之间。当两个模块之间存在紧密的耦合关系时,最好的方法就是分离接口和实现:在依赖之间定义一个抽象的接口使得高层模块调用接口,而底层模块实现接口的定义,以此来有效控制耦合关系,达到依赖于抽象的设计目标。抽象的稳定性决定了系统的稳定性,因为抽象是不变的,依赖于抽象是面向对象设计的精髓,也是依赖倒置原则的核心。依赖于抽象是一个通用的原则,而某些时候依赖于细节则是在所难免的,必须权衡在抽象和具体之间的取舍,方法不是一层不变的。依赖于抽象,就是对接口编程,不要对实现编程。
  5. 接口隔离原则(Interface-Segregation Principle):使用多个小的专门的接口,而不要使用一个大的总接口。 具体而言,接口隔离原则体现在:接口应该是内聚的,应该避免“胖”接口。一个类对另外一个类的依赖应该建立在最小的接口上,不要强迫依赖不用的方法,这是一种接口污染。分离的手段主要有以下两种:1、委托分离,通过增加一个新的类型来委托客户的请求,隔离客户和接口的直接依赖,但是会增加系统的开销。2、多重继承分离,通过接口多继承来实现客户的需求,这种方式是较好的。

面向对象的弊端

那么是不是有了面向对象以后,面向过程就完全无用了?当然不是。面向对象只不过是我们对现实世界进行抽象思考然后使用计算机符号进行表示的其中一种方式而已。其他的包括面向过程,面向函数,面向服务等等思想都有各自的应用场景。面向对象是主流方法,但在一些场景下,它也是有其劣势的。比如,在一个很小的项目中,使用面向过程就可以很方便直接解决的话,使用面向过程就可能会显得冗余了。而在一些需要更高抽象,更接近人类思考的实现时,函数式编程可能会是一个更优的方案。总之,技术思想无所谓好坏,主要还是看使用场景。能够最快速最方便解决问题,并且后遗症最少的方法就是最优解。

参考资料

  1. 什么是对象
  2. 面向对象语言的发展历史
  3. 面向对象程序设计 维基百科
  4. 面向对象思想的进化
  5. 牢记面向对象五个基本原则](https://www.hollischuang.com/archives/220)

原文地址:https://www.cnblogs.com/universal/p/10441006.html

时间: 2024-11-05 13:53:53

Java沉思录之面向对象的相关文章

C++沉思录第八章算数表达式树的面向对象问题的分析

刚开始看沉思录,觉得太枯燥.到了第八章,作者关于面向对象问题的分析,我follow书上的设计开发,理解了一些以前只是在书上看到的概念. 给自己做几点注解吧: 1.虚基类用来表达所有的继承类的共有特点,在这个例子中,所有的继承类都要有输出和求值计算,所以我们把这两个函数定义为虚函数. 2.虚基类必须至少含有一个纯虚函数.该纯虚函数可以定义也可以不定义. 3.我们要保证由虚基类派生出来的类的对象能被正确的析构,所以将虚基类的析构函数定义为虚函数. 4.对于虚函数如果没有定义,也应该使用一对{}来表明

迷你MVVM框架 avalonjs 沉思录 第1节 土耳其开局

#cnblogs_post_body p{ text-indent:2em; margin-top: 1em; } 正如一切传说的开端那样,有一远古巨神开天辟地,然后就是其他半神喧宾夺主.我们对最巨贡献与创建力的远古巨神懵懂不知,却对巫师们的话语津津乐道.这同样也是我们前端的现实. MVVM是来自.NET,另一个遥远的界域.前端,相对于后端,怎么看都是蛮夷之地.JS这个肩负着前端一切交互工作的语言,竟然被视为恶魔,屡屡被屏蔽禁用.些微可用的脚本,变量与函数没有组织地野蛮生长着,直到JAVA的传教

PHP沉思录-第六篇-Drupal的性能问题-左轻侯-《程序员》2008年11月号

创建时间:2008-11-09 01:12:51   最后修改时间:2008-11-09 01:12:51 本文发表在<程序员>杂志2008年第11期 PHP沉思录之六:Drupal的性能问题 左轻侯 Drupal是一个基于PHP的开源CMS系统,也是我认为技术上实现得最好的一个PHP应用.Drupal的架构非常优秀,通过微内核+plugin的方式,实现了极佳的扩展性,从而使Drupal远远超出一般的CMS这一范畴.从这个意义上来说,把Drupal称为Web OS似乎更加合适一些.关于Drup

沉思录:一个堕落上进者的自我救赎

人生可以归结为一种简单的选择:不是忙着活,就是忙着死.------<肖申克的救赎> 古人云:吾当三日而自省吾身.意思就是说每个人都需要自我反思.首先我们要相信群众的眼睛是雪亮的,一个人好与不好并不是自己说了算,而是他人说的和与昨天的自我对比.LZ毕业差不多快一年了,遥想刚刚毕业时的豪情壮志虽仍记忆犹新,但早已抛之九霄云外.遥记今年刚刚找了工作的种种计划,虽历历在目,但早已随风而去. 五一时有位美女说我是好男人,我说何以见得?她说你上进.努力.幽默.踏实.体贴.说我幽默也好.踏实也罢,上进.努力

RxJava 沉思录(一):你认为 RxJava 真的好用吗?

本人两年前第一次接触 RxJava,和大多数初学者一样,看的第一篇 RxJava 入门文章是扔物线写的<给 Android 开发者的 RxJava 详解>,这篇文章流传之广,相信几乎所有学习 RxJava 的开发者都阅读过.尽管那篇文章定位读者是 RxJava 入门的初学者,但是阅读完之后还是觉得懵懵懂懂,总感觉依然不是很理解这个框架设计理念以及优势. 随后工作中有机会使用 RxJava 重构了项目的网络请求以及缓存层,期间陆陆续续又重构了数据访问层,以及项目中其他的一些功能模块,无一例外,我

编程语言沉思录—编程语言的体系结构

编程语言沉思录—编程语言的体系结构 编程语言是一套描述和解释系统 一.语言体系结构: 客观世界 人(描述和解释为) 自然语言 人(描述和解释为) 编程语言 编译器() 指令集.内存地址.内存数据.内存模型 调用指令.算术指令.逻辑指令 编译器 机器指令 计算机: cpu.内存.io 二.描述和解释的细节 人将纷杂的具体事物和概念描述为编程语言. 编程语言有不同的世界观和范式,适合描述不通的问题. 对不同问题领域选择合适的语言. 编程语言是对指令集和内存等计算机体系的一种思想.领域.范式抽象. 抽

C++沉思录之二——虚函数使用的时机

虚函数使用的时机 为什么虚函数不总是适用? 1. 虚函数有事会带来很大的消耗: 2. 虚函数不总是提供所需的行为: 3. 当我们不考虑继承当前类时,不必使用虚函数. 必须使用虚函数的情况: 1. 当你想删除一个表面上指向基类对象,实际却是指向派生类对象的指针,就需要虚析构函数. C++沉思录之二--虚函数使用的时机,布布扣,bubuko.com

个性化的亲切——《沉思录》引发的感悟

记得初中那阵子,曾经追过明星,甚至美的标准也变成了他——恨不得所有的明星都是长的和他一样,唱的和他一样.除了他的歌,我几乎欣赏不了其他人的歌. 还记得差不多在那个年纪,曾经幻想过世界“大统”——我认为“大统”是达到“大同”,消弭纷争的有效方式.惭愧,后来知道希特勒也是这么想的.此乃后话,不提. 也几乎是那个时候,我不愿再做“出头鸟”,我相信“人多力量大”,我总愿意融在身边的“圈子”,不想显得自己不合群. 个性化,在我们的应试教育体制中从来都没有得到特别的提倡,如果没有良师益友的及时提点,一定会让

Trie树沉思录(1)

发现自己已经很久没有写解题报告了,很大一部分是因为懒,做完题之后不想再怎样了~不过最近发现写解题报告确实是有好处的,一方面可以复习,一方面可以梳理.还有就是可以给自己的岁月留下一点什么东西~今天是五一劳动节,就应该要劳动!我要重新着手写我的博客了~ 最近几个星期都在研究字符串,有点难,不过到现在为止Trie数学得还算是有那么点意思,写篇博文来记录一下! (关于Trie数是什么东西我就不想写了,我只写我个人的一些思考) Trie树通过共享前缀来达到了节约内存的目标,十分的强大!关于他的实现大概有两