作者: gkm422  鏈接:http://remind.javaeye.com/blog/220704  發表時間: 2008年07月28日

聲明:本文系JavaEye網站發布的原創博客文章,未經作者書面許可,嚴禁任何網站轉載本文,否則必將追究法律責任!

某天在某一家軟件公司里,那令人討厭的項目經理要求兩名程序員完成同樣的一個任務。經理并且承諾誰先完成任務的發給一張帶轉輪的真皮沙發代替原來的木質靠背椅。杰,習慣過程式編程的程序員,而濤是一個面向對象的程序員。他們都知道這是一個不錯的機會。

任務是這樣的,在GUI的程序界面里有一個正方形,一個圓形和一個正三角形。但用戶點擊這個圖形時,圖形會順時針旋轉360°并且播放相應的AIF音效。

杰,坐在自己的辦公室里,對自己說:"這個程序要做什么?我們需要那些過程?""旋轉并且播放音效。"他又回答了自己。所有他的程序就是去完成這兩個過程。

濤帶著他的筆記本坐在休息室里。他也在思索著:"程序中都有什么東西???誰是主要的角色???他最先想到的就是形狀。當然他也想到了其他的一些對象,比如用戶,音效和點擊事件。因為已經有現成的庫支持其他的對象了。因此因此他把重點放在創建形狀類上。

在杰的辦公室

就像曾經寫過千百的的程序一樣,杰把他的程序認為是重要的過程,并且沒有用什么時間就完成了旋轉和播放音效的過程。他的程序大概是這樣的

rotate (shapeNum) {
  // make the shape rotate 360°
}
playSound (shapeNum) {
// use shapeNum to lookup which AIF sound to play, and play it
}

 

濤和他的筆記本在休息室

濤為每個形狀寫了一個類

  class Square {
                rotate () {
                // code to rotate a square
                }
                playSound() {
                // code to play the AIF file for a square
                }
    }


     class Circle {
                rotate () {
                // code to rotate a circle
                }
                playSound() {
                // code to play the AIF file for a circle
                }
      }



       class Triangle{
                rotate () {
                // code to rotate a triangle
                }
                playSound() {
                // code to play the AIF file for a triangle
                }
        }

 

杰的程序基本是完成了,他覺得他贏了,他似乎已經感覺到那張真皮沙發了。

但是請等一下,任務有所變動

"現在你是快一點,杰",項目經理說著,"但我還要加一點小小的功能在程序里。這對你們這樣高水平的程序員來說,應該是毫無問題的。"

"如果只是個小改動,我可以接受。"杰想著,他知道經理所說的毫無代價的改動是胡扯。"為什么濤會顯得如此的平靜呢?"杰不解得想著。杰一直執著認為面向對象只是個花架子,完全是浪費時間。

新增的任務
在GUI界面里多了一個不規則圖形,當用戶點擊該個圖形時,圖形也會旋轉360°,并且播放一個 .hif的音效。

杰回到辦公室
旋轉的過程依然時可以用的,因為代碼使用的是shapeNum來對于相應的圖形。然而播放音效的過程需要修改。"為什么非要播放 .hif的音效呢?",杰憤憤的說著。

playSound (shapeNum) {
// if the shape is not an amoeba, 
//use shapeNum to lookup with AIF sound to play, and play it
   //else
                   //play amoeba .hif sound
   }

 

這不是一個很大的改動,但是杰依然不得不重新修改他已經調試成功過的代碼。

濤在他的筆記本前
濤微笑著,呷了一口茶。隨手寫了一個新的類。有時他覺得他最喜歡面向對象中的這個優點,就是對已經編譯調試過的代碼可以不要任何改動。靈活和課擴展形......,濤沉醉在面向對象的優點中了。

class Amoeba{
                rotate () {
                // code to rotate an amoeba
                }
                playSound() {
                // code to play the new .hif file for an amoba
                }
     }

 

杰這一次只比濤領先一步
"面向對象都是在胡扯,浪費時間!"杰正在暗笑著濤。"不規則圖形不是這樣旋轉的。"
項目經理失望的說。
原來,杰和濤都是這樣寫的
用一個矩形圍住不規則圖形,然后計算矩形的中心,最后讓圖形以中心旋轉。

項目經理接著說:"它應該以一個給定的坐標旋轉。"

"我真像是一塊砧板上任人宰割的肉。",杰想著"但我可以再加上一些if...else 語句就可以搞定了。"然而天知道經理會又有什么改動呢?

杰的辦公室
他思索著旋轉的過程。很多的代碼受到影響的。杰又要重新編譯調試。終于有了結果。

                rotate ( shapeNum, xPt, yPt) {
                // if the shape is not an amoeba,
                        //calculate the center point base on the rectangle, the rotate
                //else
                        //use the xPt and yPt as the rotation point offset an the rotate
                }

 

濤在他的筆記本前
為了不把沙發拱手讓給杰,濤也在修改他的旋轉方法,但僅僅是在Amoeba的類里。對于其他的測試好的類,是原封不動的。為了給不規則圖形一個旋轉點,他給Amoeba加肋兩個屬性,然后他測完成后通過無線網絡提交了任務。

class Amoeba{
                int xPoint;
                int yPoint;
                rotate () {
                // code to rotate an amoeba using amoeba's x and y
                }
                playSound() {
                // code to play the new .hif file for an amoba
                }
}

 

那濤得到了沙發對嗎?

并沒有那么快,杰找到濤程序里的一個缺陷。并且他知道如果能得到沙發的話就可以取悅會計室的婷,因此他不希望就這樣就輸了。

下面是杰和濤的對話
杰:你的代碼大量重復,你的旋轉過程在四個圖形的東西里都有。

濤:這是方法,不是過程。還有他們是類,不叫做東西。

杰:不管叫什么,你的設計簡直是垃圾。你要處理四個不同旋轉"方法"。你怎么處理???

濤:我猜你是沒看見最后的設計。讓我告訴你繼承在面向對象中書如何工作的??催@四個類是有共同點的。它們都有rotate()和playSound()


于是我抽象出一個Shape類來

abstract class Shape(){
        rotate();
        playSound();
}

 

然后我讓這四個類繼承這個抽象的類

class Square extends Shape {
                rotate () {
                // code to rotate a square
                }
                playSound() {
                // code to play the AIF file for a square
                }
}

class Circle extends Shape {
                rotate () {
                // code to rotate a circle
                }
                playSound() {
                // code to play the AIF file for a circle
                }
}
class Triangle extends Shape {
                rotate () {
                // code to rotate a triangle
                }
                playSound() {
                // code to play the AIF file for a triangle
                }
}

class Amoeba extends Sharpe{
                int xPoint;
                int yPoint;
                rotate () {
                // code to rotate an amoeba using amoeba's x and y
                }
                playSound() {
                // code to play the new .hif file for an amoba
                }
}

 

那Amoeba的類旋轉呢?
杰:問題不是就在這嗎?Amoeba有完全不同的旋轉和播放音效的過程嗎?

濤:是方法。

杰:不管是它叫什么了。Amoeba怎么能實現與他說繼承的類shape不同的事呢?

濤:這是最后一遍了。Amoeba重騎(overrides)了Shape類的方法。在運行時(runtime)Java的虛擬機(JVM)知道但程序需要Amoeba去旋轉時應該調用相應的方法。

杰:你怎么告訴Amoeba去旋轉???難道你們不要調用過程,哦不對,是方法然后告訴它應該那個圖形去旋轉嗎?

濤:這就是面向對象的好處所在了。比如說,要讓三角形旋轉。程序調用Triangle對象的rotate( )方法。程序的其他部分不知道也不在于三角形形是怎么轉的。當你要想添加一點功能到程序中時,你只要寫一個為新的對象類型寫一個新的類,那個新的對象有自己的特性。

杰:我希望我也能成為一個面向對象的程序員,這太神奇了。

后記

這是半年多來,我所看過的Java的文章中,對面向對象講解的最生動的一篇。因為是英文的,所以一直放在那里。也曾試著寫一個類似的例子。因為水平有限一直沒有完成。很久沒有給論壇點好東西了。于是用了三天的時間把它翻譯改編出來了。也找到這篇原版的PDF。

當然這篇文章只是一個啟發性的東西。要了解并且熟悉面向對象,需要的是時間和實踐。你自己不去看點東西,寫點東西,當然會被什么類啊,對象啊搞得云里霧里的啊。

這是一個令人浮躁的年代。什么動畫啊,視頻教程的汗牛充棟。不能否認,這些東西生動直觀。然而輕易得來得東西,也會輕易的忘記的快。

我又多嘴了。最后再嘮叨幾句吧。面向對象是個好東西啊。當然如果你寫程序只是為了編譯一些什么溢出工具什么的,那可以不去理解什么是面向對象。但如果你真的想搞點大的,有商業前途的東西,面向對象的思想是一定要有的。

 


本文的討論也很精彩,瀏覽討論>>


JavaEye推薦




文章來源:http://remind.javaeye.com/blog/220704