从Rob Pike 的 Google+上的一个推看到了一篇叫《Understanding Object Oriented Programming》的文章,我先把这篇文章简述一下,然后再说说老牌黑客Rob Pike的评论。
先看这篇教程是怎么来讲述OOP的。它先给了下面这个问题,这个问题需要输出一段关于操作系统的文字:假设Unix很不错,Windows很差。
这个把下面这段代码描述成是Hacker Solution。(这帮人觉得下面这叫黑客?我估计这帮人真是没看过C语言的代码)
public class PrintOS
{
public static void main(finalString[] args)
{
String osName = System.getProperty("os.name") ;
if(osName.equals("SunOS") || osName.equals("Linux"))
{
System.out.println("This is a UNIX box and therefore good.") ;
}
elseif(osName.equals("Windows NT") || osName.equals("Windows 95"))
{
System.out.println("This is a Windows box and therefore bad.") ;
}
else
{
System.out.println("This is not a box.") ;
}
}
}
然后开始用面向对象的编程方式一步一步地进化这个代码。
先是以过程化的思路来重构之。

过程化的方案
public class PrintOS
{
private static String unixBox()
{
return"This is a UNIX box and therefore good.";
}
private static String windowsBox()
{
return"This is a Windows box and therefore bad.";
}
private static String defaultBox()
{
return"This is not a box.";
}
private static String getTheString(finalString osName)
{
if(osName.equals("SunOS") || osName.equals("Linux"))
{
returnunixBox() ;
}
elseif(osName.equals("Windows NT") ||osName.equals("Windows 95"))
{
returnwindowsBox() ;
}
else
{
returndefaultBox() ;
}
}
public static void main(finalString[] args)
{
System.out.println(getTheString(System.getProperty("os.name"))) ;
}
}
然后是一个幼稚的面向对象的思路。

幼稚的面向对象编程
PrintOS.java
publicclassPrintOS
{
publicstaticvoidmain(finalString[] args)
{
System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ;
}
}

OSDiscriminator.java
publicclassOSDiscriminator// Factory Pattern
{
privatestaticBoxSpecifier theBoxSpecifier =null;
publicstaticBoxSpecifier getBoxSpecifier()
{
if(theBoxSpecifier ==null)
{
String osName = System.getProperty("os.name") ;
if(osName.equals("SunOS") || osName.equals("Linux"))
{
theBoxSpecifier =newUNIXBox() ;
}
elseif(osName.equals("Windows NT") || osName.equals("Windows 95"))
{
theBoxSpecifier =newWindowsBox() ;
}
else
{
theBoxSpecifier =newDefaultBox () ;
}
}
returntheBoxSpecifier ;
}
}

BoxSpecifier.java
publicinterfaceBoxSpecifier
{
String getStatement() ;
}

DefaultBox.java
publicclassDefaultBoximplementsBoxSpecifier
{
publicString getStatement()
{
return"This is not a box.";
}
}

UNIXBox.java
publicclassUNIXBoximplementsBoxSpecifier
{
publicString getStatement()
{
return"This is a UNIX box and therefore good.";
}
}

WindowsBox.java
publicclassWindowsBoximplementsBoxSpecifier
{
publicString getStatement()
{
return"This is a Windows box and therefore bad.";
}
}
他们觉得上面这段代码没有消除if语句,他们说这叫代码的“logic bottleneck”(逻辑瓶颈),因为如果你要增加一个操作系统的判断的话,你不但要加个类,还要改那段if-else的语句。
所以,他们整出一个叫Sophisticated的面向对象的解决方案。

OO大师的方案
注意其中的Design Pattern

PrintOS.java
publicclassPrintOS
{
publicstaticvoidmain(finalString[] args)
{
System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ;
}
}

OSDiscriminator.java
publicclassOSDiscriminator// Factory Pattern
{
privatestaticjava.util.HashMap storage =newjava.util.HashMap() ;

publicstaticBoxSpecifier getBoxSpecifier()
{
BoxSpecifier value = (BoxSpecifier)storage.get(System.getProperty("os.name")) ;
if(value ==null)
returnDefaultBox.value ;
returnvalue ;
}
publicstaticvoidregister(finalString key,finalBoxSpecifier value)
{
storage.put(key, value) ;// Should guard against null keys, actually.
}
static
{
WindowsBox.register() ;
UNIXBox.register() ;
MacBox.register() ;
}
}

BoxSpecifier.java
publicinterfaceBoxSpecifier
{
String getStatement() ;
}

DefaultBox.java
publicclassDefaultBoximplementsBoxSpecifier// Singleton Pattern
{
publicstaticfinalDefaultBox value =newDefaultBox () ;
privateDefaultBox() { }
publicString getStatement()
{
return"This is not a box.";
}
}

UNIXBox.java
publicclassUNIXBoximplementsBoxSpecifier// Singleton Pattern
{
publicstaticfinalUNIXBox value =newUNIXBox() ;
privateUNIXBox() { }
public String getStatement()
{
return"This is a UNIX box and therefore good.";
}
publicstaticfinalvoidregister()
{
OSDiscriminator.register("SunOS", value) ;
OSDiscriminator.register("Linux", value) ;
}
}

WindowsBox.java
publicclassWindowsBoximplementsBoxSpecifier // Singleton Pattern
{
public static final WindowsBox value =new WindowsBox() ;
privateWindowsBox() { }
publicString getStatement()
{
return"This is a Windows box and therefore bad.";
}
publicstaticfinalvoidregister()
{
OSDiscriminator.register("Windows NT", value) ;
OSDiscriminator.register("Windows 95", value) ;
}
}

MacBox.java
publicclassMacBoximplementsBoxSpecifier// Singleton Pattern
{
publicstaticfinalMacBox value =newMacBox() ;
privateMacBox() { }
public String getStatement()
{
return"This is a Macintosh box and therefore far superior.";
}
publicstaticfinalvoidregister()
{
OSDiscriminator.register("Mac OS", value) ;
}
}
作者还非常的意地说,他加了一个“Mac OS”的东西。老实说,当我看到最后这段OO大师搞出来的代码,我快要吐了。我瞬间想到了两件事:一个是以前酷壳上的《面向对象是个骗局》和 《各种流行的编程方式》中说的“设计模式驱动编程”,另一个我想到了那些被敏捷洗过脑的程序员和咨询师,也是这种德行。
于是我去看了一下第一作者Joseph Bergin的主页,这个Ph.D是果然刚刚完成了一本关于敏捷和模式的书。
Rob Pike的评论
(Rob Pike是当年在Bell lab里和Ken一起搞Unix的主儿,后来和Ken开发了UTF-8,现在还和Ken一起搞Go语言。注:不要以为Ken和Dennis是基友,其实他们才是真正的老基友!)
Rob Pike在他的Google+的这贴里评论到这篇文章——
他并不确认这篇文章是不是搞笑?但是他觉得这些个写这篇文章是很认真的。他说他要评论这篇文章是因为他们是一名Hacker,至少这个词出现在这篇文章的术语中。
他说,这个程序根本就不需要什么Object,只需要一张小小的配置表格,里面配置了对应的操作系统和你想输出的文本。这不就完了。这么简单的设计,非常容易地扩展,他们那个所谓的Hack Solution完全就是笨拙的代码。后面那些所谓的代码进化相当疯狂和愚蠢的,这个完全误导了对编程的认知。
然后,他还说,他觉得这些OO的狂热份子非常害怕数据,他们喜欢用多层的类的关系来完成一个本来只需要检索三行数据表的工作。他说他曾经听说有人在他的工作种用各种OO的东西来替换While循环。(我听说中国Thoughtworks那帮搞敏捷的人的确喜欢用Object来替换所有的if-else语句,他们甚至还喜欢把函数的行数限制在10行以内)
他还给了一个链接http://prog21.dadgum.com/156.html,你可以读一读。最后他说,OOP的本质就是——对数据和与之关联的行为进行编程。便就算是这样也不完全对,因为:
Sometimes data is just data and functions are just functions.
我的理解
我觉得,这篇文章的例子举得太差了,差得感觉就像是OO的高级黑。面向对象编程注重的是:1)数据和其行为的打包封装,2)程序的接口和实现的解耦。你那怕,举一个多个开关和多个电器的例子,不然就像STL中,一个排序算法对多个不同容器的例子,都比这个例子要好得多得多。老实说,Java SDK里太多这样的东西了。
我以前给一些公司讲一些设计模式的培训课,我一再提到,那23个经典的设计模式和OO半毛钱关系没有,只不过人家用OO来实现罢了。设计模式就三个准则:1)中意于组合而不是继承,2)依赖于接口而不是实现,3)高内聚,低耦合。你看,这完全就是Unix的设计准则。
(全文完)

C++——OOP面向对象理解的更多相关文章

  1. c#基础-oop(面向对象理解)

    OOP-面向对象 封装,继承多态 一个桌子,用面向对象来描述一下它这个桌子项目 定义桌子类 对象:桌子 桌子的属性:名字,材质,体积 桌子的方法;放东西(方法) 现在桌子要放书,放花瓶,放文件(这里就 ...

  2. js面向对象理解

    js面向对象理解 ECMAScript 有两种开发模式:1.函数式(过程化),2.面向对象(OOP).面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象.但是, ...

  3. OOP面向对象 三大特征 继承封装多态

    OOP面向对象 ----三大特征 继承封装多态 面向对象(Object Oriented,OO)是软件开发方法.面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统.交互式界面.应用结构 ...

  4. OOP面向对象三大特点

    OOP面向对象三大特点 (一)封装:将现实中一个事物的属性和功能集中定义在一个对象中.(创建对象) 创建对象的3种方式: 1.直接量方式:(创建一个单独的对象) var obj={ 属性名:值,    ...

  5. 我个人对OOP的理解

    OOP面向对象的思维:pay1:封装 A.避免使用非法数据赋值 B.保证数据的完整性 C.避免类内部发生修改的时候,导致整个程序的修改 pay2:继承 A.继承模拟了现实世界的关系,OOP中强调一切皆 ...

  6. OOP 面向对象 七大原则 (二)

    OOP 面向对象   七大原则 (二) 上一篇写到了前四个原则,这一篇继续~~ 接口隔离:客户端不应该依赖它不需要的接口:一个类对另一个类的依赖应该建立在最小的接口上. 又是一句大白话~就是说接口尽量 ...

  7. OOP 面向对象 七大原则 (一)

    OOP 面向对象   七大原则 (一) 大家众所周知,面向对象有三大特征继承封装多态的同时,还具有这七大原则,三大特征上一篇已经详细说明,这一篇就为大家详解一下七大原则: 单一职责原则,开闭原则,里氏 ...

  8. 用C实现OOP面向对象编程(1)

    如摘要所说,C语言不支持OOP(面向对象的编程).并这不意味着我们就不能对C进行面向对象的开发,只是过程要复杂许多.原来以C++的许多工作,在C语言中需我们手动去完成. 博主将与大家一起研究一下如下用 ...

  9. OOP面向对象程序设计原则

    OOP面向对象程序设计原则 开闭原则(Open Close Principle) 对扩展开放,对修改关闭 里氏代换原则(Liskov Substitution Principle) 继承必须确保超累所 ...

随机推荐

  1. 廖老师的Python教程——安装Python

    因为Python是跨平台的,它可以运行在Windows.Mac和各种Linux/Unix系统上.在Windows上写Python程序,放到Linux上也是能够运行的. 要开始学习Python编程,首先 ...

  2. OMAPL138制作SD卡启动介质及重装Linux系统

    OMAPL138制作SD卡启动盘及重装Linux系统 手里的创龙的OMAPL138平台的系统SSH坏掉了,我重新移植了openssh还是不好使,没有办法了只能重装OMAPL138的系统了,按照创龙给的 ...

  3. 005---基于UDP的套接字

    基于UDP的套接字 udp不同于tcp协议:不需要经过三次握手.四次挥手.直接发送数据就行. 服务端 import socket ip_port = ('127.0.0.1', 8001) buffe ...

  4. 最短路径算法 2.Dijkstra算法

    Dijkstra 算法解决的是带权重的有向图上单源最短路径问题,该算法要求所有边的权重都为非负值.该算法的时间复杂度是O(N2),相比于处理无负权的图时,比Bellmad-Ford算法效率更高. 算法 ...

  5. Spring MVC怎么统一异常管理?

    1. 在类上加上@ControllerAdvice注解 2. 在方法上加上@ExceptionHandler注解 @ExceptionHandler(Exception.class) @Respons ...

  6. linux挂载命令mount及U盘、移动硬盘的挂载

    一.mount的命令格式是(注意mount只能在root权限下运行) mount dervice dir dervice是要挂载的设备,dir是挂载点 二.查看当前磁盘列表的设备 fdisk -l 显 ...

  7. stm32--USB(作为U盘)+FatFs的实现

    一.USB功能的添加(作为U盘) 添加文件 将官方库中的Library文件夹中的所有有效文件添加到工程中,分为4个文件夹: usb class为硬件相关(Library\Class): usb dri ...

  8. OpenCV入门:(二:加载,显示,修改以及保存图片)

    目标: 1.从图片文件打开图片(imread) 2.显示图片(namedWindow和imshow) 3.转换当前图片为灰色图片(cvtColor) 4.保存图片(imwrite) 代码: #incl ...

  9. 【个人笔记】关于C++小数的处理

    无论是C-Style还是C++-Style的输出,小数都会四舍五入.如果想要截断两种比较好的方法.第一种:利用sscanf输出成字符串,再人为地putchar().第二种:已知钦定保留6位小数,那么可 ...

  10. Linux-Shell脚本编程-学习-1-Linux基本命令

    在学习Linux-Shell脚本编程之前,我们需要学习一定的Linux基本命令,不然在后面学习Shell脚本编程的的时候,我们就呵呵了. 我学习所用的系统是Ubuntu 16.04版本 也没有什么规则 ...