如此理解面向对象编程
从Rob Pike 的 Google+上的一个推看到了一篇叫《Understanding Object Oriented Programming》的文章,我先把这篇文章简述一下,然后再说说老牌黑客Rob Pike的评论。
先看这篇教程是怎么来讲述OOP的。它先给了下面这个问题,这个问题需要输出一段关于操作系统的文字:假设Unix很不错,Windows很差。
这个把下面这段代码描述成是Hacker Solution。(这帮人觉得下面这叫黑客?我估计这帮人真是没看过C语言的代码)
public class PrintOS { public static void main(final String[] 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.") ; } else if (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(final String osName) { if (osName.equals("SunOS") || osName.equals("Linux")) { return unixBox() ; } else if (osName.equals("Windows NT") ||osName.equals("Windows 95")) { return windowsBox() ; } else { return defaultBox() ; } } public static void main(final String[] args) { System.out.println(getTheString(System.getProperty("os.name"))) ; } }
然后是一个幼稚的面向对象的思路。
幼稚的面向对象编程
public class PrintOS { public static void main(final String[] args) { System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ; } }
public class OSDiscriminator // Factory Pattern { private static BoxSpecifier theBoxSpecifier = null ; public static BoxSpecifier getBoxSpecifier() { if (theBoxSpecifier == null) { String osName = System.getProperty("os.name") ; if (osName.equals("SunOS") || osName.equals("Linux")) { theBoxSpecifier = new UNIXBox() ; } else if (osName.equals("Windows NT") || osName.equals("Windows 95")) { theBoxSpecifier = new WindowsBox() ; } else { theBoxSpecifier = new DefaultBox () ; } } return theBoxSpecifier ; } }
public interface BoxSpecifier { String getStatement() ; }
public class DefaultBox implements BoxSpecifier { public String getStatement() { return "This is not a box." ; } }
public class UNIXBox implements BoxSpecifier { public String getStatement() { return "This is a UNIX box and therefore good." ; } }
public class WindowsBox implements BoxSpecifier { public String getStatement() { return "This is a Windows box and therefore bad." ; } }
他们觉得上面这段代码没有消除if语句,他们说这叫代码的“logic bottleneck”(逻辑瓶颈),因为如果你要增加一个操作系统的判断的话,你不但要加个类,还要改那段if-else的语句。
所以,他们整出一个叫Sophisticated的面向对象的解决方案。
OO大师的方案
注意其中的Design Pattern
public class PrintOS { public static void main(final String[] args) { System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ; } }
public class OSDiscriminator // Factory Pattern { private static java.util.HashMap storage = new java.util.HashMap() ; public static BoxSpecifier getBoxSpecifier() { BoxSpecifier value = (BoxSpecifier)storage.get(System.getProperty("os.name")) ; if (value == null) return DefaultBox.value ; return value ; } public static void register(final String key, final BoxSpecifier value) { storage.put(key, value) ; // Should guard against null keys, actually. } static { WindowsBox.register() ; UNIXBox.register() ; MacBox.register() ; } }
public interface BoxSpecifier { String getStatement() ; }
public class DefaultBox implements BoxSpecifier // Singleton Pattern { public static final DefaultBox value = new DefaultBox () ; private DefaultBox() { } public String getStatement() { return "This is not a box." ; } }
public class UNIXBox implements BoxSpecifier // Singleton Pattern { public static final UNIXBox value = new UNIXBox() ; private UNIXBox() { } public String getStatement() { return "This is a UNIX box and therefore good." ; } public static final void register() { OSDiscriminator.register("SunOS", value) ; OSDiscriminator.register("Linux", value) ; } }
public class WindowsBox implements BoxSpecifier // Singleton Pattern { public static final WindowsBox value = new WindowsBox() ; private WindowsBox() { } public String getStatement() { return "This is a Windows box and therefore bad." ; } public static final void register() { OSDiscriminator.register("Windows NT", value) ; OSDiscriminator.register("Windows 95", value) ; } }
public class MacBox implements BoxSpecifier // Singleton Pattern { public static final MacBox value = new MacBox() ; private MacBox() { } public String getStatement() { return "This is a Macintosh box and therefore far superior." ; } public static final void register() { 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,至少这个词出现在这篇文章的术语中。
他说,这个程序根本�