前言
作为编程初学者,经常会听到人们说面向对象编程,而自己平常写的代码都是面向过程的,根本不懂:面向对象到底是什么东西,有什么好处,我们为什么要使用面向对象编程以及什么时候使用面向对象编程等一系列问题。看完这篇文章,你或许会有所体会。
面向对象与面向过程的区别
何谓面向对象编程(OOP)?
从概念上来说,用对象的思想去写代码,就是面向对象编程。
编写程序通常有两种模式
- 面向过程编程
- 面向对象编程
- 面向过程编程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;
- 面向对象编程是把问题分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
举个例子
你接到一个需求,要把一个冰淇淋装进冰箱,面向过程,你会把过程拆成3步
- 打开冰箱
- 放入冰淇淋
- 关闭冰箱
这时你可能会分别写好3个函数来一一实现这3步
1 | function 冰箱开门(){...} |
然后依次调用函数
1 | 冰箱开门(); |
你可能为了使函数变得更加灵活实用,改造成1
2
3
4
5
6
7
8function 开门(什么开门){...}
function 装进(什么开门,装进什么){...}
function 关门(什么关门){...}
//调用
开门(冰箱);
装进(冰箱, 冰淇淋);
关门(冰箱);
这样即使下一次不在冰箱放入冰淇淋,而是在微波炉放入鸡腿,只要调用时传入微波炉和鸡腿参数即可满足需求。
- 可以看出:
面向过程时,强调的是动作,对象只是被传进动作的参数。
如果是面向对象,写法侧重点就会不一样
我们会先把开门关门等方法写进构造函数
,然后通过构造函数new
出对象,new出来的对象就具有了构造函数里面的各种方法和属性。
何谓构造函数?
构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。
1 | //javascript |
面向对象时,强调的是对象,动作只是被对象执行的方法。
仔细对比上面的代码,不难发现面向对象的写法比面向过程要复杂。那么我们为什么还要用面向对象呢?
其实对于同一个需求来说,面向对象和面向过程都能够实现,只是写法上面有差异。
需求不多时面向过程还能应付过来,但是随着需求、可复用场景的增多与业务逻辑的复杂化,面向过程的写法会越来越难维护,每次需求的变更,我们就要把整个系统通读一遍,找出可用的函数(如果没有就再定义一个),最后依次调用它们。
面向对象从另一个角度来解决这个问题。它抛弃了函数,把「对象」作为程序的基本单元。
我们把对象的通用属性和方法整合起来,放进一个构造函数,这样可以提高代码的复用性。每次想要一个带有通用属性和方法的对象,只需要用这个构造函数new一次,没有的功能我们单独为new出来的对象添加。
假如你接手一个面向对象写出来的项目,需求变更时通用的方法和属性往往不需要去管,只需修改指定的对象,维护起来也比较容易。因为继承
和封装
的特性,修改代码对程序整体的影响将降到最低。
沿用上面的例子来举例,我们想要冰箱具有自动开门的功能,我们只需为冰箱加入自动开门功能1
2
3
4
5
6
7
8
9
10
11
12
13//javascript
function 构造函数(){...}
构造函数.prototype.开门 = function (){...};
构造函数.prototype.装进 = function (装进什么){...};
构造函数.prototype.关门 = function (){...};
//调用
var 冰箱 = new 构造函数();
冰箱.prototype.自动开门 = function (){...};
冰箱.自动开门();
var 微波炉 = new 构造函数();
微波炉.自动开门(); //报错
- 在上述的例子中,我们把同时具有开门,装进,关门方法的对象
抽象
为同一个类
。 - 通过这个类new出来一个新对象(冰箱),我们称之为
实例化
。 - 可以为冰箱添加自动关门新功能,添加后构造函数(父类)不受影响,这也是
继承
的概念。 - 只有冰箱才能使用这个新功能,微波炉使用会报错,这就是
封装
的概念。 - 此时对放入功能进行改造,作用在冰箱上,冰箱自动使用冷藏功能;作用在微波炉上,微波炉自动使用加热功能,这就是
多态
的概念。
类(Class):具有相似属性和行为的一组对象,就称为类。
抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征。
抽象性是指将具有一致的数据结构(属性)和行为(操作)的对象抽象成类。一个类就是这样一种抽象,它反映了与应用有关的重要性质,而忽略其他一些无关内容。任何类的划分都是主观的,但必须与具体的应用有关。
实例化是指在面向对象的编程中,通常把用类创建对象的过程称为实例化。
继承 是面向对象软件技术当中的一个概念,与多态、封装共为面向对象的三个基本特征。 继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。
封装:隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读取和修改的访问级别。
多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性。
面向对象与面向过程的优缺点
面向对象
- 优点:易维护、易复用、易扩展,健壮性好。由于面向对象有封装、继承、多态性的特性,使得应用程序的修改带来的影响更加局部化(低耦合),因此使用面向对象设计的系统更加灵活、更加易于维护。
- 缺点:性能比面向过程低,每次实例化都要占用一定内存空间,但是随着硬件性能的提升,这个缺点变得越来越不明显。
面向过程
- 优点:面向过程的程序更容易编写,逻辑性更强,性能比面向对象好,更适合底层开发。
- 缺点:拓展性,可维护性,复用性都不如面向对象,加上容易出现全局变量污染等问题,因此健壮性也不如面向对象。
参考
