由一次项目实施引发的过程与对象的对话

发表于:2007-05-25来源:作者:点击数: 标签:项目引发一次过程对象
某天在某一家软件公司里,那令人讨厌的项目经理要求两名 程序员 完成同样的一个任务。经理并且承诺谁先完成任务的发给一张带转轮的真皮沙发代替原来的木质靠背椅。Jackie,习惯过程式编程的程序员,而Paul是一个 面向对象 的程序员。他们都知道这是一个不错
某天在某一家软件公司里,那令人讨厌的项目经理要求两名程序员完成同样的一个任务。经理并且承诺谁先完成任务的发给一张带转轮的真皮沙发代替原来的木质靠背椅。Jackie,习惯过程式编程的程序员,而Paul是一个面向对象的程序员。他们都知道这是一个不错的机会。

任务是这样的,在GUI的程序界面里有一个正方形,一个圆形和一个正三角形。但用户点击这个图形时,图形会顺时针旋转360°并且播放相应的AIF音效。

Jackie坐在自己的办公室里,对自己说:“这个程序要做什么?我们需要那些过程?”“旋转并且播放音效。”她又回答了自己。所有她的程序就是去完成这两个过程。

Paul带着他的笔记本坐在休息室里。他也在思索着:“程序中都有什么东西啊?谁是主要的角色啊?他最先想到的就是形状。当然他也想到了其他的一些对象,比如用户,音效和点击事件。因为已经有现成的库支持其他的对象了。因此因此他把重点放在创建形状类上。

在Jackie的办公室

就像曾经写过千百的的程序一样,Jackie把他的程序认为是重要的过程,并且没有用什么时间就完成了旋转和播放音效的过程。他的程序大概是这样的

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

Paul和他的笔记本在休息室

Paul为每个形状写了一个类

 

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

Jackie的程序基本是完成了,她觉得她赢了,她似乎已经感觉到那张真皮沙发了。但是请等一下,任务有所变动

“现在你是快一点,Jackie”,项目经理说着,“但我还要加一点小小的功能在程序里。这对你们这样高水平的程序员来说,应该是毫无问题的。”

“如果只是个小改动,我可以接受。”Jackie想着,她知道经理所说的毫无代价的改动是胡扯。“为什么Paul会显得如此的平静呢?”Jackie不解的想着。Jackie一直执着认为面向对象只是个花架子,完全是浪费时间。

新增的任务是在GUI界面里多了一个不规则图形,当用户点击该个图形时,图形也会旋转360°,并且播放一个 .hif的音效。

Jackie回到办公室

旋转的过程依然时可以用的,因为代码使用的是shapeNum来对于相应的图形。然而播放音效的过程需要修改。“为什么非要播放 .hif的音效呢?”,Jackie愤愤的说着。

 

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
            }

这不是一个很大的改动,但是Jackie依然不得不重新修改她已经调试成功过的代码。Paul在他的笔记本前,微笑着,呷了一口茶。随手写了一个新的类。有时他觉得他最喜欢面向对象中的这个优点,就是对已经编译调试过的代码可以不要任何改动。灵活和课扩展形……,Paul沉醉在面向对象的优点中了。

 

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

Jackie这一次只比Paul领先一步

“面向对象都是在胡扯,浪费时间!”Jackie正在暗笑着Paul。“不规则图形不是这样旋转的。”项目经理失望的说。原来,Jackie和Paul都是这样写的:用一个矩形围住不规则图形,然后计算矩形的中心,最后让图形以中心旋转。项目经理接着说:“它应该以一个给定的坐标旋转。”

“我真像是一块砧板上任人宰割的肉。”,Jackie想着“但我可以再加上一些if…else 语句就可以搞定了。”然而天知道经理会又有什么改动呢?

Jackie的办公室

他思索着旋转的过程。很多的代码受到影响的。Jackie又要重新编译调试。终于有了结果。

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
            }

Paul在他的笔记本前

为了不把沙发拱手让给Jackie,Paul也在修改他的旋转方法,但仅仅是在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
            }
            }

那Paul得到了沙发对吗?

并没有那么快,Jackie找到Paul程序里的一个缺陷。她不希望就这样就输了。下面是Jackie和Paul的对话:

Jackie:你的代码大量重复,你的旋转过程在四个图形的东西里都有。

Paul:这是方法,不是过程。还有他们是类,不叫做东西。

Jackie:不管叫什么,你的设计简直是垃圾。你要处理四个不同旋转“方法”。你怎么处理啊?

Paul:我猜你是没看见最后的设计。让我告诉你继承在面向对象中书如何工作的。看这四个类是有共同点的。它们都有

 

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的类旋转呢?

Jackie:问题不是就在这吗?Amoeba有完全不同的旋转和播放音效的过程吗?

Paul:是方法。

Jackie:不管是它叫什么了。Amoeba怎么能实现与他说继承的类shape不同的事呢?

Paul:这是最后一遍了。Amoeba重骑(overrides)了Shape类的方法。在运行时(runtime)Java的虚拟机(JVM)知道但程序需要Amoeba去旋转时应该调用相应的方法。

Jackie:你怎么告诉Amoeba去旋转啊?难道你们不要调用过程,不对,是方法然后告诉它应该那个图形去旋转吗?

Paul:这就是面向对象的好处所在了。比如说,要让三角形旋转。程序调用Triangle对象的rotate()方法。程序的其他部分不知道也不在于三角形形是怎么转的。当你要想添加一点功能到程序中时,你只要写一个为新的对象类型写一个新的类,那个新的对象有自己的特性。

Jackie:我希望我也能成为一个面向对象的程序员,这太神奇了。

原文转自:http://www.ltesting.net

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)