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) 继承必须确保超累所 ...
随机推荐
- 出现java.lang.NoSuchMethodError错误的原因
作为Java开发者我们都遇到过java.lang.NoSuchMethodError错误,究其根源,是JVM的"双亲委托模型"引发的问题.如果在类路径下放置了多个不同版本的类包,如 ...
- 吐血分享:QQ群霸屏技术教程(利润篇)
QQ群技术,不论日进几百,空隙时间多的可以尝试,日进100问题不大. QQ群技术,如何赚钱,能赚多少钱?不同行业,不同关键词,不同力度,不一样的产出. 群费 群费,这个和付费群是有区别的,群费在手机端 ...
- 事物总线模式实例——EventBus实例详解
事件总线模式是一种广泛运用于安卓开发之中的一种软件架构模式,而事件总线模式在安卓开发中最广泛的应用莫过于AndroidStudio提供的EventBus,所以我就EventBus来谈谈对事件总线模式的 ...
- hive的desc命令
desc命令 desc 命令是为了展示hive表格的内在属性.例如列名,data_type,存储位置等信息.这个命令常常用在我们对hive表格观察之时,我们想要知道这个hive各个列名(基于这些具体列 ...
- Leecode刷题之旅-C语言/python-21.合并两个有序链表
/* * @lc app=leetcode.cn id=21 lang=c * * [21] 合并两个有序链表 * * https://leetcode-cn.com/problems/merge-t ...
- IO复用——poll系统调用
1.poll函数 #include<poll.h> int poll(struct pollfd* fds, nfds_t ndfs, int timeout) poll函数在一定的时间内 ...
- B -- POJ 1208 The Blocks Problem
参考:https://blog.csdn.net/yxz8102/article/details/53098575 https://www.cnblogs.com/tanjuntao/p/867892 ...
- Hadoop数据倾斜及解决办法
数据倾斜:就是大量的相同key被partition分配到一个分区里,map /reduce程序执行时,reduce节点大部分执行完毕,但是有一个或者几个reduce节点运行很慢,导致整个程序的处理时间 ...
- uwsgi配置文件
[uwsgi] http = :9000 #the local unix socket file than commnuincate to Nginx #socket端口这个用作nginx与其通讯 s ...
- android activity状态保存
一.被其他任务打断(来电话),再次打开希望保留数据 private String SAVE_INSTANCE_TAG = "ATWAL"; @Override protected ...