熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

如此理解面向對象編程

2013-11-23 19:27:21  來源: Java核心技術 

  從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 = SystemgetProperty(osname) ;   
           if (osNameequals(SunOS) || osNameequals(Linux))   
           {   
               Systemoutprintln(This is a UNIX box and therefore good) ;   
           }   
           else if (osNameequals(Windows NT) || osNameequals(Windows ))   
           {   
               Systemoutprintln(This is a Windows box and therefore bad) ;   
           }   
           else 
           {   
               Systemoutprintln(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 (osNameequals(SunOS) || osNameequals(Linux))   
           {   
               return unixBox() ;   
           }   
           else if (osNameequals(Windows NT) ||osNameequals(Windows ))   
           {   
               return windowsBox() ;   
           }   
           else 
           {   
               return defaultBox() ;   
           }   
       }   
       public static void main(final String[] args)   
       {   
           Systemoutprintln(getTheString(SystemgetProperty(osname))) ;   
       }   
   } 

  然後是一個幼稚的面向對象的思路

  幼稚的面向對象編程 

  PrintOSjava

  public class PrintOS   
   {   
       public static void main(final String[] args)   
       {   
           Systemoutprintln(OSDiscriminatorgetBoxSpecifier()getStatement()) ;   
       }   
   } 

  OSDiscriminatorjava

  public class OSDiscriminator // Factory Pattern   
   {   
       private static BoxSpecifier theBoxSpecifier = null ;   
       public static BoxSpecifier getBoxSpecifier()   
       {   
           if (theBoxSpecifier == null)   
           {   
               String osName = SystemgetProperty(osname) ;   
               if (osNameequals(SunOS) || osNameequals(Linux))   
               {   
                   theBoxSpecifier = new UNIXBox() ;   
               }   
               else if (osNameequals(Windows NT) || osNameequals(Windows ))   
               {   
                   theBoxSpecifier = new WindowsBox() ;   
               }   
               else 
               {   
                   theBoxSpecifier = new DefaultBox () ;   
               }   
           }   
           return theBoxSpecifier ;   
       }   
   } 

  BoxSpecifierjava

  public interface BoxSpecifier   
   {   
       String getStatement() ;   
   } 

  DefaultBoxjava

  public class DefaultBox implements BoxSpecifier   
   {   
       public String getStatement()   
       {   
           return This is not a box ;   
       }   
   } 

  UNIXBoxjava

  public class UNIXBox implements BoxSpecifier   
   {   
       public String getStatement()   
       {   
           return This is a UNIX box and therefore good ;   
       }   
   } 

  WindowsBoxjava

  public class WindowsBox implements BoxSpecifier   
   {   
       public String getStatement()   
       {   
           return This is a Windows box and therefore bad ;   
       }   
   } 

  他們覺得上面這段代碼沒有消除if語句他們說這叫代碼的logic bottleneck(邏輯瓶頸)因為如果你要增加一個操作系統的判斷的話你不但要加個類還要改那段ifelse的語句

  所以他們整出一個叫Sophisticated的面向對象的解決方案

  OO大師的方案

  注意其中的Design Pattern

  PrintOSjava

  public class PrintOS   
   {   
       public static void main(final String[] args)   
       {   
           Systemoutprintln(OSDiscriminatorgetBoxSpecifier()getStatement()) ;   
       }   
   } 

  OSDiscriminatorjava

  public class OSDiscriminator // Factory Pattern   
   {   
       private static javautilHashMap storage = new javautilHashMap() ;   
       
       public static BoxSpecifier getBoxSpecifier()   
       {   
           BoxSpecifier value = (BoxSpecifier)storageget(SystemgetProperty(osname)) ;   
           if (value == null)   
               return DefaultBoxvalue ;   
           return value ;   
       }   
       public static void register(final String key final BoxSpecifier value)   
       {   
           storageput(key value) ; // Should guard against null keys actually   
       }   
       static 
       {   
           WindowsBoxregister() ;   
           UNIXBoxregister() ;   
           MacBoxregister() ;   
       }   
   } 

  BoxSpecifierjava

  public interface BoxSpecifier   
   {   
       String getStatement() ;   
   } 

  DefaultBoxjava

  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 ;   
       }   
   } 

  UNIXBoxjava

  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()   
       {   
           OSDiscriminatorregister(SunOS value) ;   
           OSDiscriminatorregister(Linux value) ;   
       }   
   } 

  WindowsBoxjava

  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()   
       {   
           OSDiscriminatorregister(Windows NT value) ;   
           OSDiscriminatorregister(Windows  value) ;   
       }   
   } 

  MacBoxjava

  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()   
       {   
           OSDiscriminatorregister(Mac OS value) ;   
       }   
   } 

  作者還非常的意地說他加了一個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的設計准則


From:http://tw.wingwit.com/Article/program/Java/hx/201311/26893.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.