【思考】再谈面向过程与面向对象

在我博客创作早期,写了一篇博文,名字是【Java核心技术卷】面向过程与面向对象对比。

这篇文章试图对比描述了关于 面向过程与面向对象 的内容。为什么还要再谈呢?

一方面原因是深度不够,另一方面原因要从对各种编程语言的感知说起 (涵盖面向对象、面向过程):

  • 编译执行的C语言是静态语言、弱类型语言。
  • 解释执行的JavaScript语言是动态语言、弱类型语言。
  • 混合编译执行的Java是静态语言、强类型语言。

如果你不太明白静态语言和动态语言以及强类型与弱类型,看文末的补充内容。

似乎有很多独特的“语言”,而且每一种语言背后都有非常深的“技术”蕴含其中。

之前也曾就C语言,Java,Python,JavaScript这四种语言对比过它们的跨平台能力,翻译成机器码执行的过程,详情参见【Java核心技术卷】面向对象与面向过程语言对比

为了帮助你复习一遍,这里仅仅展示文章里面的四张图:

? C语言

? Java语言

? JavaScript语言

? Python语言

但是无论是 面向过程,还是面向对象, 肯定都有相通之处,也有区别所在。

面向过程就不多说,基本是C的天下了。

那么对于面向对象呢?

? 我们这里首先谈论一下面向对象的相通之处:


面向对象有着三大基本特征

  1. 封装
  2. 继承
  3. 多态

这个你就比较熟悉了。

封装:
把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
类将成员变量和成员函数封装在类的内部,根据需要设置访问权限,通过成员函数管理内部状态。

继承:
继承所表达的是类之间相关的关系,这种关系使得对象可以继承另外一类对象的特征和能力。
继承的作用:避免公用代码的重复开发,减少代码和数据冗余。

多态
多态性可以简单地概括为“一个接口,多种方法”,字面意思为多种形态。程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念。

但是插句题外话,你知道你所熟悉的语言的"继承"与“多态”是如何实现的嘛?
关于Java的话可以参考这三篇文章
【Java核心技术卷】了解Java的内存逻辑对象模型
【Java核心技术卷】理解Java的继承与多态重要概念
【Java核心技术卷】深入理解Java的动态绑定,静态绑定和多态


不知道你是否学过设计模式的相关内容,像UML、七大软件设计原则、二十三种设计模式 它们中有很多的东西都是面向对象所通用的,里面深刻地体现着面向对象的思想。

有一句话说的很好:“使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样”

建议每个人都要好好琢磨琢磨。


那你听说过面向对象的五大基本原则吗?

  1. 单一职责原则(Single-Responsibility Principle)
  2. 开放封闭原则(Open-Closed principle)
  3. Liskov替换原则(Liskov-Substituion Principle)
  4. 依赖倒置原则(Dependency-Inversion Principle)
  5. 接口隔离原则(Interface-Segregation Principle)

其实这五条也是七大软件设计原则中的内容,我们看吧~

七大软件设计原则 可以参考【Java设计模式】软件设计七大原则
实现语言是 Java哈,因为有举例所以更好理解一些。

面向对象的五大基本原则 文字叙述部分

这部分内容参考了网上的资料,但是因为来源过多,无法注明出处了。

一、 单一职责原则(Single-Resposibility Principle)

其核心思想为:一个类,最好只做一件事,只有一个引起它的变化。

单一职责原则可以看做是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。

职责过多,可能引起它变化的原因就越多,这将导致职责依赖,相互之间就产生影响,从而大大损伤其内聚性和耦合度。

通常意义下的单一职责,就是指只有一种单一功能,不要为类实现过多的功能点,以保证实体只有一个引起它变化的原因。

单一是一个类的优良设计。交杂不清的职责将使得代码看起来特别别扭牵一发而动全身,有失美感和必然导致丑陋的系统错误风险。

二、开放封闭原则(Open-Closed principle)

其核心思想是:软件实体应该是可扩展的,而不可修改的。也就是,对扩展开放,对修改封闭的。

开放封闭原则主要体现在两个方面:
1、对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。
2、对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对其进行任何尝试的修改。

实现开开放封闭原则的核心思想就是对抽象编程,而不对具体编程,因为抽象相对稳定。让类依赖于固定的抽象,所以修改就是封闭的;而通过面向对象的继承和多态机制,又可以实现对抽象类的继承,通过覆写其方法来改变固有行为,实现新的拓展方法,所以就是开放的。

“需求总是变化”没有不变的软件,所以就需要用封闭开放原则来封闭变化满足需求,同时还能保持软件内部的封装体系稳定,不被需求的变化影响。

三、Liskov替换原则(Liskov-Substituion Principle)

其核心思想是:子类必须能够替换其基类。

这一思想体现为对继承机制的约束规范,只有子类能够替换基类时,才能保证系统在运行期内识别子类,这是保证继承复用的基础。

在父类和子类的具体行为中,必须严格把握继承层次中的关系和特征,将基类替换为子类,程序的行为不会发生任何变化。同时,这一约束反过来则是不成立的,子类可以替换基类,但是基类不一定能替换子类。

Liskov替换原则,主要着眼于对抽象和多态建立在继承的基础上,因此只有遵循了Liskov替换原则,才能保证继承复用是可靠地。

实现的方法是面向接口编程:将公共部分抽象为基类接口或抽象类,通过Extract Abstract Class,在子类中通过覆写父类的方法实现新的方式支持同样的职责。

Liskov替换原则是关于继承机制的设计原则,违反了Liskov替换原则就必然导致违反开放封闭原则。

Liskov替换原则能够保证系统具有良好的拓展性,同时实现基于多态的抽象机制,能够减少代码冗余,避免运行期的类型判别。

四、 依赖倒置原则(Dependecy-Inversion Principle)

其核心思想是:依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象。

我们知道,依赖一定会存在于类与类、模块与模块之间。当两个模块之间存在紧密的耦合关系时,最好的方法就是分离接口和实现:在依赖之间定义一个抽象的接口使得高层模块调用接口,而底层模块实现接口的定义,以此来有效控制耦合关系,达到依赖于抽象的设计目标。

抽象的稳定性决定了系统的稳定性,因为抽象是不变的,依赖于抽象是面向对象设计的精髓,也是依赖倒置原则的核心。

依赖于抽象是一个通用的原则,而某些时候依赖于细节则是在所难免的,必须权衡在抽象和具体之间的取舍,方法不是一层不变的。依赖于抽象,就是对接口编程,不要对实现编程。

五、接口隔离原则(Interface-Segregation Principle)

其核心思想是:使用多个小的专门的接口,而不要使用一个大的总接口。

具体而言,接口隔离原则体现在:接口应该是内聚的,应该避免“胖”接口。一个类对另外一个类的依赖应该建立在最小的接口上,不要强迫依赖不用的方法,这是一种接口污染。

接口有效地将细节和抽象隔离,体现了对抽象编程的一切好处,接口隔离强调接口的单一性。而胖接口存在明显的弊端,会导致实现的类型必须完全实现接口的所有方法、属性等;而某些时候,实现类型并非需要所有的接口定义,在设计上这是“浪费”,而且在实施上这会带来潜在的问题,对胖接口的修改将导致一连串的客户端程序需要修改,有时候这是一种灾难。在这种情况下,将胖接口分解为多个特点的定制化方法,使得客户端仅仅依赖于它们的实际调用的方法,从而解除了客户端不会依赖于它们不用的方法。

分离的手段主要有以下两种:
1、委托分离,通过增加一个新的类型来委托客户的请求,隔离客户和接口的直接依赖,但是会增加系统的开销。
2、多重继承分离,通过接口多继承来实现客户的需求,这种方式是较好的。

以上就是5个基本的面向对象设计原则,它们就像面向对象程序设计中的金科玉律,遵守它们可以使我们的代码更加鲜活,易于复用,易于拓展,灵活优雅。不同的设计模式对应不同的需求,而设计原则则代表永恒的灵魂,需要在实践中时时刻刻地遵守。就如ARTHUR J.RIEL在那边《OOD启示录》中所说的:“你并不必严格遵守这些原则,违背它们也不会被处以宗教刑罚。但你应当把这些原则看做警铃,若违背了其中的一条,那么警铃就会响起。”

为了让代码更加完美,我们往往会重构它,如果能够很好遵守这5个基本的面向对象设计原则,并且有着良好的单元测试习惯,那么重构将不会一下子变得无比艰难。

? 那面向对象的语言的区别呢?

这范围可就广了,用我熟悉的Java和C++说一下吧,通过对比,我们是能够学到东西的:

?

C++ 被设计成主要用在系统性应用程序设计上的语言,对C语言进行了扩展。对于C语言, C++ 特别加上了以下这些特性的支持:静态类型的面向对象程序设计的支持、异常处理、RAII以及泛型。另外它还加上了一个包含泛型容器和算法的C++库函数。

Java 依赖一个虚拟机来保证安全和可移植性。Java包含一个可扩展的库用以提供一个完整的的下层平台的抽象。Java是一种静态面向对象语言,它使用的语法类似C++,但与之不兼容。为了使更多的人到使用更易用的语言,它进行了全新的设计。

?

C++是编译型语言(首先将源代码编译生成机器语言,再由机器运行机器码),执行速度快、效率高;依赖编译器、跨平台性差些。

Java是混合型语言(源代码不是直接翻译成机器语言,而是先翻译成中间代码,再由解释器对中间代码进行解释运行。),执行速度慢、效率低;依赖解释器、跨平台性好。

?

C++是平台相关的

Java是平台无关的。

?

C++对所有的数字类型有标准的范围限制,但字节长度是跟具体实现相关的,不同操作系统可能。

Java在所有平台上对所有的基本类型都有标准的范围限制和字节长度。

?

C++除了一些比较少见的情况之外和C语言兼容 。

Java没有对任何之前的语言向前兼容。但在语法上受 C/C++ 的影响很大

?

C++允许直接调用本地的系统库 。

Java要通过JNI调用, 或者 JNA

?
C++允许过程式程序设计和面向对象程序设计 。

Java必须使用面向对象的程序设计方式

?

C++支持指针,引用,传值调用 。

Java只有值传递。

Java只有值传递 , 这个 你不好奇吗?

?

C++需要显式的内存管理,但有第三方的框架可以提供垃圾搜集的支持。支持析构函数。

Java 是自动垃圾收集的。没有析构函数的概念。

?
C++支持多重继承,包括虚拟继承 。

Java只允许单继承,需要多继承的情况要使用接口。

千万不要把自己限制死了,通过比较能拓宽我们的见识。

最后补充一下上面需要参考的内容:

静态类型语言、动态类型语言分析:

静态类型语言:变量定义时有类型声明的语言。
1)变量的类型在编译的时候确定
2)变量的类型在运行时不能修改
这样编译器就可以确定运行时需要的内存总量。
例如:C/C++/Java/C#语言是静态类型语言。

动态类型语言:变量定义时无类型声明的语言。
1)变量的类型在运行的时候确定
2)变量的类型在运行可以修改
例如:Javascript语言是动态类型语言。
由于动态类型和静态类型语言的特性衍生出强类型语言和弱类型、无类型语言。

强类型语言、弱类型、无类型语言:
弱/强类型指的是语言类型系统的类型检查的严格程度。弱类型相对于强类型来说类型检查更不严格,比如说允许变量类型的隐式转换,允许强制类型转换等等。

  • 强类型语言:例如Java/C#语言是强类型语言,强类型定义语言是类型安全的语言,是由编译器以及编译器生成的中间代码来保证类型安全。
  • 弱类型语言:C/C++/Javascript语言是弱类型语言,其类型安全由程序员来保证,Javascript语言的安全由程序员来保证。
    无类型语言:是动态语言,变量中既可以存放数据又可以存放代码。

【思考】再谈面向过程与面向对象相关推荐

  1. 面向过程和面向对象的联系和区别

    以C语言和C++为例. C语言是面向过程的,封装单元是函数.函数里面按照逻辑流程一步一步实现就行了,这符合我们现实生活中解决问题时的思考过程. C++是面向对象的,封装单元是类.首先,面向对象是为了提 ...

  2. 架构师之路---面向过程和面向对象 王泽宾

    1.引言    机算机科学是一门应用科学,它的知识体系是典型的倒三角结构,所用的基础知识并不多,只是随着应用领域和方向的不同,产生了很多的分支,所以说编程并不是一件很困难的事情,一个高中生经过特定的训 ...

  3. 带你理解面向过程与面向对象

    START WeChat Applet(公众号) :Java空巷 一.前言 如果你总是对面向对象和面向过程傻傻分不清,这篇博客尽量会用通俗的方式来讲解. 二.面向过程 概念 面向过程是一种以过程为中心 ...

  4. 什么是面向过程与面向对象

    什么是面向过程与面向对象 许多人在学习语言的时候都会被告知,C语言是面向过程的编程语言,JAVA语言是面向对象的编程语言等等. 这时当你是刚学习一门语言的时候,根本就不用管这个概念是什么意思,因为你是 ...

  5. 什么是面向对象、面向过程与面向对象的区别

    要讲区别,首先我们得先来弄弄清楚什么是面向过程,什么是面向对象. 面向过程是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了. 比如把大象放进冰箱,第一 ...

  6. 初学JAVA-8-对象和类、面向过程和面向对象

    其实本来准备这篇笔记先写数组,再通过Scanner引入简单的人机交互,之后再引出对象和类,面向过程和面向对象这个话题的.但是我思考了半天,还是决定先时候说对象和类.面向过程和面向对象这些事情.从我写第 ...

  7. 面向过程和面向对象编程的优缺点

    [1]面向过程和面向对象的比较 网上发现了一篇文章,说了一下OP与OO的不同,并且打了一个比喻,通俗易懂. 有人这么形容OP和OO的不同:用面向过程的方法写出来的程序是一份蛋炒饭,而用面向对象写出来的 ...

  8. 架构师之路(1)---面向过程和面向对象

    1.引言    机算机科学是一门应用科学,它的知识体系是典型的倒三角结构,所用的基础知识并不多,只是随着应用领域和方向的不同,产生了很多的分支,所以说编程并不是一件很困难的事情,一个高中生经过特定的训 ...

  9. 面向过程 VS 面向对象

    面向过程(Process Oriented)这个词是在面向对象(Object Oriented)出现之后为与之相对而提出的.其实它在以前基本被叫做"结构化编程". 早期的程序设计, ...

  10. java面向过程编程怎么写_从面向过程到面向对象,我的编程之路

    也许现在新一代的程序员一开始涉足的就是c++,C#,Java这类面向对象的语言,如果这样,这篇文章可能得不到他们的认同. 这里,我只想写写我从面向过程到面向对象开发成长中的一些感想而已. 我最初学习的 ...

最新文章

  1. ASP.NET中实现打印
  2. ES transport client使用
  3. Cocos2d-xna : 横版战略游戏开发实验5 TiledMap实现关卡地图
  4. [深度学习] 自然语言处理--- 基于Keras Bert使用(上)
  5. linux脚本登录启动失败,linux – 在X上运行shell脚本失败登录尝试
  6. Unity 编辑器内建图标获得
  7. oracle数据块dump信息,从数据块的dump信息能看出什么
  8. 首批 8 款 5G 手机获 3C 认证;iPhone6 系列停产;Android Q Beta 5 发布 | 极客头条
  9. 1213家中国厂商涌入拉斯维加斯!CES 2019最全预告在此...
  10. android中新建文件夹在哪里,Android SdCard 新建文件夹并在文件夹中读、写文件
  11. SAP中的client
  12. 计算机内存分为两种他们是,计算机内存主要有哪两种?他们的主要特点是什么?...
  13. onlyoffice5.4.2离线包的制作—解决中文字体问题
  14. 【解题报告】2014ACM/ICPC亚洲区广州站
  15. Visual Studio 2019 Compiler Hangs
  16. 厦门理工学院oj1717
  17. windows10 导入 oracle11g dmp文件方法(详细!!!)
  18. Windows 鼠标右键注册表位置
  19. Java 43---SpringMVC框架(1)
  20. 20201215记一次502错误

热门文章

  1. 基于MATLAB的数字信号处理(5) FIR数字滤波器设计及软件实现
  2. 小米路由器 mini 重新刷回官方固件
  3. [SCOI2009]粉刷匠 两个dp
  4. 两年小前端裸辞求职经历
  5. java ckfinder 图片重命名,CKEditor CKFinder图片上传
  6. 文件 MD5 SHA1 SHA256 SHA512 校验码生成工具 V1.3
  7. transition详解【过渡属性】
  8. 《精通python设计模式》读书笔记之——行为型设计模式
  9. 网络会变的有自我意识吗
  10. CMM(软件能力成熟度模型)