`
gkm422
  • 浏览: 81684 次
  • 性别: Icon_minigender_1
  • 来自: 太原
社区版块
存档分类
最新评论

沙发之争(过程与对象的对话)

阅读更多

某天在某一家软件公司里,那令人讨厌的项目经理要求两名程序员完成同样的一个任务。经理并且承诺谁先完成任务的发给一张带转轮的真皮沙发代替原来的木质靠背椅。杰,习惯过程式编程的程序员,而涛是一个面向对象的程序员。他们都知道这是一个不错的机会。

任务是这样的,在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。

当然这篇文章只是一个启发性的东西。要了解并且熟悉面向对象,需要的是时间和实践。你自己不去看点东西,写点东西,当然会被什么类啊,对象啊搞得云里雾里的啊。

这是一个令人浮躁的年代。什么动画啊,视频教程的汗牛充栋。不能否认,这些东西生动直观。然而轻易得来得东西,也会轻易的忘记的快。

我又多嘴了。最后再唠叨几句吧。面向对象是个好东西啊。当然如果你写程序只是为了编译一些什么溢出工具什么的,那可以不去理解什么是面向对象。但如果你真的想搞点大的,有商业前途的东西,面向对象的思想是一定要有的。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics