C++——OOP面向对象理解
从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面向对象理解的更多相关文章
- c#基础-oop(面向对象理解)
OOP-面向对象 封装,继承多态 一个桌子,用面向对象来描述一下它这个桌子项目 定义桌子类 对象:桌子 桌子的属性:名字,材质,体积 桌子的方法;放东西(方法) 现在桌子要放书,放花瓶,放文件(这里就 ...
- js面向对象理解
js面向对象理解 ECMAScript 有两种开发模式:1.函数式(过程化),2.面向对象(OOP).面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象.但是, ...
- OOP面向对象 三大特征 继承封装多态
OOP面向对象 ----三大特征 继承封装多态 面向对象(Object Oriented,OO)是软件开发方法.面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统.交互式界面.应用结构 ...
- OOP面向对象三大特点
OOP面向对象三大特点 (一)封装:将现实中一个事物的属性和功能集中定义在一个对象中.(创建对象) 创建对象的3种方式: 1.直接量方式:(创建一个单独的对象) var obj={ 属性名:值, ...
- 我个人对OOP的理解
OOP面向对象的思维:pay1:封装 A.避免使用非法数据赋值 B.保证数据的完整性 C.避免类内部发生修改的时候,导致整个程序的修改 pay2:继承 A.继承模拟了现实世界的关系,OOP中强调一切皆 ...
- OOP 面向对象 七大原则 (二)
OOP 面向对象 七大原则 (二) 上一篇写到了前四个原则,这一篇继续~~ 接口隔离:客户端不应该依赖它不需要的接口:一个类对另一个类的依赖应该建立在最小的接口上. 又是一句大白话~就是说接口尽量 ...
- OOP 面向对象 七大原则 (一)
OOP 面向对象 七大原则 (一) 大家众所周知,面向对象有三大特征继承封装多态的同时,还具有这七大原则,三大特征上一篇已经详细说明,这一篇就为大家详解一下七大原则: 单一职责原则,开闭原则,里氏 ...
- 用C实现OOP面向对象编程(1)
如摘要所说,C语言不支持OOP(面向对象的编程).并这不意味着我们就不能对C进行面向对象的开发,只是过程要复杂许多.原来以C++的许多工作,在C语言中需我们手动去完成. 博主将与大家一起研究一下如下用 ...
- OOP面向对象程序设计原则
OOP面向对象程序设计原则 开闭原则(Open Close Principle) 对扩展开放,对修改关闭 里氏代换原则(Liskov Substitution Principle) 继承必须确保超累所 ...
随机推荐
- Hadoop(6)-HDFS的shell操作
1.基本语法 使用 hadoop fs 具体命令 或者 hdfs dfs 具体命令 hadoop命令的shell源码 hdfs命令的shell源码 由此可见,这两个命令最后都是执行的一个jav ...
- mysql根据二进制日志恢复数据/公司事故实战经验
根据二进制日志恢复 目的:恢复数据,根据二进制日志将数据恢复到今天任意时刻 增量恢复,回滚恢复 如果有备份好的数据,将备份好的数据导入新数据库时,会随着产生二进制日志 先准备一台初始化的数据库 mys ...
- 640. Solve the Equation
class Solution { public: string solveEquation(string equation) { int idx = equation.find('='); , v1 ...
- (杭电 1097)A hard puzzle
A hard puzzle Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- JavaScript之this解析
1.解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象我们称为函数执行的上下文对象,根据函数的调用方式不同,this会指向不同的对象 ...
- python2.7入门---file(文件)&OS 文件&目录方法
首先file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数: 序号 方法及描述 1 file.close() 关闭文件.关闭后文件不能再进行读写操作. 2 file.f ...
- Linq中dbSet 的查询
1.Find:按照关键字的ID号来查询(速度快) 如: ADShiTi aDShiTi = db.ADShiTis.Find(id); 2.FirstOrDefault:根据部分条件查询,显示最前的一 ...
- elasticsearch-mathc和term的区分
elasticsearch和mysql在思想上是有不同的,elasticsearch有分词一说,比如北京奥运分词成北京,奥运,北京奥运.分词要要考虑两点,一个是查询字符串要不要分词,还有就是原存储字段 ...
- C#属性默认值设置
关于在MVC中view中设置默认值,可以象如下设置: 1.关于VIEWMODEL的部分 如果是C# 6.0,网上资料查到说可以 如果语法不支持,只能改回.net 2.0的写法. public cla ...
- springmvc常用jar包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans ...