欢迎光临

木子屋

标题: 过程式编程vs面向对象编程[转]

作者: dnawo

日期: 2015-01-07 05:55 PM

分类: 网络文摘

内容: 过程式编程和面向对象编程的区别并不在于是否使用函数或者类，也就是说用到类或对象的可能是过程式编程，只用函数而没有类的也可能是面向对象编程。那么他们的区别又在哪儿呢？
过程式编程
维基百科是这样定义过程式编程的（Procedural Programming）：过程式编程某种意义上等同于命令式编程（为了达到预定的状态而执行指定的步骤）的同义词，同时也是一种编程范例（正如本文中所述）——由结构化编程衍生而来，遵循过程调用的观念。
这是一个很恰当的定义，但我们还可以改进它。我更赞同“过程式编程只是一系列为了实现需求功能的特定步骤的命令”这一观点。它究竟是如何实现的只是细节，与范例无关，重要的是它是工作所必要的。先来看几个例子：
这个很明显是过程式编程：
复制内容到剪贴板 程序代码 = mysqli_connect(...);
= mysqli_query(, );
= array();
while ( = mysqli_fetch_assoc()) {
[] = ;
}
虽然用到了对象，但它实际上也是过程式编程：
复制内容到剪贴板 程序代码 = new MySQLi(...);
= ->query();
= array();
while ( = ->fetch_assoc()) {
[] = ;
}
即使使用了类，它还是过程式编程：
复制内容到剪贴板 程序代码class GetResults {
public function getResults() {
= new MySQLi(...);
= ->query();
= array();
while ( = ->fetch_assoc()) {
[] = ;
}
return ;
}
}
注意：上述几个例子使用了完全相同的代码框，它们之间的不同点在于如何实现的，但都是过程式编程，都包含必须的独立步骤。再来看看什么才是面向对象编程，它们之间的不同之处又在哪？
面向对象编程
维基百科上是这样定义面向对象编程（Object-Oriented Programming）的：面向对象编程是使用对象的编程范式——包含数据域、方法以及它们之间的交互——来设计应用和程序。编程技术包括包括数据抽象、封装、通信、模块化、多态和继承。
这个定义也不错，但我只同意它的第二部分。第一部分所说的“必须使用对象来做面向对象编程”很明显是错误的，你完全可以通过数据抽象、封装、通信、模块化、多态和继承等方式实现数据抽象。
我对于面向对象编程的几点理解是：
首先，它必须将数据抽象为模块结构；
其次，必须存在某种方式来实现代码的多态执行；
最后，它至少能部分压缩代码和函数。
下面再看看几个例子：
经典面向对象编程模式：
复制内容到剪贴板 程序代码class Mediator {
protected = array();
public function attach(, ) {
if (!isset(->events[])) {
->events[] = array();
}
->events[][] = ;
}
public function trigger(, = null) {
foreach (->events[] as ) {
(, );
}
}
}
= new Mediator;
->attach('load', function() { echo "Loading"; });
->attach('stop', function() { echo "Stopping"; });
->attach('stop', function() { echo "Stopped"; });
->trigger('load'); // prints "Loading"
->trigger('stop'); // prints "StoppingStopped"
相同的模式，但使用函数：
复制内容到剪贴板 程序代码 = array();
function hook_register(, ) {
if (!isset(['hooks'][])) {
['hooks'][] = array();
}
['hooks'][][] = ;
}
function hook_trigger(, = null) {
foreach (['hooks'][] as ) {
(, );
}
}
如你所见，它们都遵循传递者模式（Mediator Pattern），并且被设计为从sender中解耦caller，所以都是面向对象的。都提供状态、都是模块化的。不同点在于：第一个是通过传统的类实现的（因此可重用，这也是使用类的一个优势），而第二个使用了全局变量，并不可重用。我在这里使用“hook”，这是一个Drupal使用的事件系统。
Drupal是一个很好的例子，它的模块系统、“hook”系统、结构系统都是面向对象的，但都不是使用对象实现的，它是使用函数和动态分配，这导致了很多尴尬的折中，我并不是说这是一个好的面向对象，只是证明类并不是面向对象编程所必须的因素。
为什么这很重要？
很简单，因为很多开发者认为他们使用了类就是在做面向对象编程；另一些人认为他们使用函数就是在做过程式编程了，这并不正确。过程式编程和面向对象编程都是一种写代码的途径，而不是你写代码的手段。你会遵循步骤，按照设定好的方式去编写程序吗？你看起来是在函数式编程，但是如果你专注于状态改变和密封抽象，你就是在用面向对象编程。
类只是帮助简化面向对象编程的工具，并不是面向对象编程的要求或指示器。
面向对象编程与数据库存取
那面向对象编程里的数据库存取又是什么样的呢？面向对象编程的数据库存取是完全抽象的，我的方法是：
复制内容到剪贴板 程序代码 = new PersonDataMapper(new MySQLi(...));
= ->getAll();
people是一个person对象的数组。注意：像这样抽象很有必要，所有事物对象无法直接对数据库操作，你需要一个映射器来翻译事物对象和数据存储之间的转换。一个专门的映射器会在内部创建请求，执行并返回结果。但这完全是抽象的，我们可以简单地换掉映射器来改变数据库层实现细节。
数据持久化的责任变成了封装抽象，这也就是为什么它是面向对象编程而不是过程式编程。
原文链接：http://www.csdn.net/article/2012-07-16/2807372

+ 查看当前日志评论 (0)

登录

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 1.094 ms

返回

标题: 过程式编程vs面向对象编程[转]

你没有权限发表评论

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 1.094 ms

返回

暂无评论

返回

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 1.117 ms

返回