从Rob Pike 的 Google+上的一个推看到了一篇叫《Understanding Object Oriented Programming》的文章我先把这篇文章简述一下然后再说说老牌黑客Rob Pike的评论 先看这篇教程是怎么来讲述OOP的它先给了下面这个问题这个问题需要输出一段关于操作系统的文字假设Unix很不错Windows很差 这个把下面这段代码描述成是Hacker Solution(这帮人觉得下面这叫黑客?我估计这帮人真是没看过C语言的代码) publicclassPrintOS { publicstaticvoidmain(finalString[]args) { StringosName=SystemgetProperty(osname); if(osNameequals(SunOS)||osNameequals(Linux)) { Systemoutprintln(ThisisaUNIXboxandthereforegood); } elseif(osNameequals(WindowsNT)||osNameequals(Windows)) { Systemoutprintln(ThisisaWindowsboxandthereforebad); } else { Systemoutprintln(Thisisnotabox); } } } 然后开始用面向对象的编程方式一步一步地进化这个代码 先是以过程化的思路来重构之 过程化的方案 publicclassPrintOS { privatestaticStringunixBox() { returnThisisaUNIXboxandthereforegood; } privatestaticStringwindowsBox() { returnThisisaWindowsboxandthereforebad; } privatestaticStringdefaultBox() { returnThisisnotabox; } privatestaticStringgetTheString(finalStringosName) { if(osNameequals(SunOS)||osNameequals(Linux)) { returnunixBox(); } elseif(osNameequals(WindowsNT)||osNameequals(Windows)) { returnwindowsBox(); } else { returndefaultBox(); } } publicstaticvoidmain(finalString[]args) { Systemoutprintln(getTheString(SystemgetProperty(osname))); } } 然后是一个幼稚的面向对象的思路 幼稚的面向对象编程 PrintOSjava publicclassPrintOS { publicstaticvoidmain(finalString[]args) { Systemoutprintln(OSDiscriminatorgetBoxSpecifier()getStatement()); } } OSDiscriminatorjava publicclassOSDiscriminator//FactoryPattern { privatestaticBoxSpecifiertheBoxSpecifier=null; publicstaticBoxSpecifiergetBoxSpecifier() { if(theBoxSpecifier==null) { StringosName=SystemgetProperty(osname); if(osNameequals(SunOS)||osNameequals(Linux)) { theBoxSpecifier=newUNIXBox(); } elseif(osNameequals(WindowsNT)||osNameequals(Windows)) { theBoxSpecifier=newWindowsBox(); } else { theBoxSpecifier=newDefaultBox(); } } returntheBoxSpecifier; } } BoxSpecifierjava publicinterfaceBoxSpecifier { StringgetStatement(); } DefaultBoxjava publicclassDefaultBoximplementsBoxSpecifier { publicStringgetStatement() { returnThisisnotabox; } } UNIXBoxjava publicclassUNIXBoximplementsBoxSpecifier { publicStringgetStatement() { returnThisisaUNIXboxandthereforegood; } } WindowsBoxjava publicclassWindowsBoximplementsBoxSpecifier { publicStringgetStatement() { returnThisisaWindowsboxandthereforebad; } } 他们觉得上面这段代码没有消除if语句他们说这叫代码的logic bottleneck(逻辑瓶颈)因为如果你要增加一个操作系统的判断的话你不但要加个类还要改那段ifelse的语句 所以他们整出一个叫Sophisticated的面向对象的解决方案 OO大师的方案 注意其中的Design Pattern PrintOSjava publicclassPrintOS { publicstaticvoidmain(finalString[]args) { Systemoutprintln(OSDiscriminatorgetBoxSpecifier()getStatement()); } } OSDiscriminatorjava publicclassOSDiscriminator//FactoryPattern { privatestaticjavautilHashMapstorage=newjavautilHashMap(); publicstaticBoxSpecifiergetBoxSpecifier() { BoxSpecifiervalue=(BoxSpecifier)storageget(SystemgetProperty(osname)); if(value==null) returnDefaultBoxvalue; returnvalue; } publicstaticvoidregister(finalStringkeyfinalBoxSpecifiervalue) { storageput(keyvalue);//Shouldguardagainstnullkeysactually } static { WindowsBoxregister(); UNIXBoxregister(); MacBoxregister(); } } BoxSpecifierjava publicinterfaceBoxSpecifier { StringgetStatement(); } DefaultBoxjava publicclassDefaultBoximplementsBoxSpecifier//SingletonPattern { publicstaticfinalDefaultBoxvalue=newDefaultBox(); privateDefaultBox(){} publicStringgetStatement() { returnThisisnotabox; } } UNIXBoxjava publicclassUNIXBoximplementsBoxSpecifier//SingletonPattern { publicstaticfinalUNIXBoxvalue=newUNIXBox(); privateUNIXBox(){} publicStringgetStatement() { returnThisisaUNIXboxandthereforegood; } publicstaticfinalvoidregister() { OSDiscriminatorregister(SunOSvalue); OSDiscriminatorregister(Linuxvalue); } } WindowsBoxjava publicclassWindowsBoximplementsBoxSpecifier//SingletonPattern { publicstaticfinalWindowsBoxvalue=newWindowsBox(); privateWindowsBox(){} publicStringgetStatement() { returnThisisaWindowsboxandthereforebad; } publicstaticfinalvoidregister() { OSDiscriminatorregister(WindowsNTvalue); OSDiscriminatorregister(Windowsvalue); } } MacBoxjava publicclassMacBoximplementsBoxSpecifier//SingletonPattern { publicstaticfinalMacBoxvalue=newMacBox(); privateMacBox(){} publicStringgetStatement() { returnThisisaMacintoshboxandthereforefarsuperior; } publicstaticfinalvoidregister() { OSDiscriminatorregister(MacOSvalue); } } 作者还非常的意地说他加了一个Mac OS的东西老实说当我看到最后这段OO大师搞出来的代码我快要吐了我瞬间想到了两件事一个是以前酷壳上的《面向对象是个**》和 《各种流行的编程方式》中说的设计模式驱动编程另一个我想到了那些被敏捷洗过脑的程序员和咨询师也是这种德行 于是我去看了一下第一作者Joseph Bergin的主页这个PhD是果然刚刚完成了一本关于敏捷和模式的书 Rob Pike的评论 (Rob Pike是当年在Bell lab里和Ken一起搞Unix的主儿后来和Ken开发了UTF现在还和Ken一起搞Go语言注不要以为Ken和Dennis是基友其实他们才是真正的老基友!) Rob Pike在他的Google+的这贴里评论到这篇文章—— 他并不确认这篇文章是不是搞笑?但是他觉得这些个写这篇文章是很认真的他说他要评论这篇文章是因为他们是一名Hacker至少这个词出现在这篇文章的术语中 他说这个程序根本就不需要什么Object只需要一张小小的配置表格里面配置了对应的操作系统和你想输出的文本这不就完了这么简单的设计非常容易地扩展他们那个所谓的Hack Solution完全就是笨拙的代码后面那些所谓的代码进化相当疯狂和愚蠢的这个完全误导了对编程的认知 然后他还说他觉得这些OO的狂热份子非常害怕数据他们喜欢用多层的类的关系来完成一个本来只需要检索三行数据表的工作他说他曾经听说有人在他的工作种用各种OO的东西来替换While循环(我听说中国Thoughtworks那帮搞敏捷的人的确喜欢用Object来替换所有的ifelse语句他们甚至还喜欢把函数的行数限制在行以内) 他还给了一个链接你可以读一读最后他说OOP的本质就是——对数据和与之关联的行为进行编程便就算是这样也不完全对因为 Sometimes data is just data and functions are just functions 我的理解 我觉得这篇文章的例子举得太差了差得感觉就像是OO的高级黑面向对象编程注重的是)数据和其行为的打包封装)程序的接口和实现的解耦你那怕举一个多个开关和多个电器的例子不然就像STL中一个排序算法对多个不同容器的例子都比这个例子要好得多得多老实说Java SDK里太多这样的东西了 我以前给一些公司讲一些设计模式的培训课我一再提到那个经典的设计模式和OO半毛钱关系没有只不过人家用OO来实现罢了设计模式就三个准则)中意于组合而不是继承)依赖于接口而不是实现)高内聚低耦合你看这完全就是Unix的设计准则 |