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.") ;
}
}
}
而後開始用面向對象的編程方式一步一步地進化這個代碼。
先是以過程化的思路來重構之。html

過程化的方案
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"))) ;
}
}
而後是一個幼稚的面向對象的思路。java


幼稚的面向對象編程
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() ;
}
}windows

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的設計準則。(全文完)

相關文章
相關標籤/搜索