友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
狗狗书籍 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

Java编程思想第4版[中文版](PDF格式)-第255章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




  static double val = 0。23f;  

  Glass(double wt) { super(wt); }  

  double value() { return val; }  

  static void value(double newval) {  

    val = newval;  

  }  

}  

  

public class RecycleA {  

  public static void main(String'' args) {  

    Vector bin = new Vector();  

    // Fill up the Trash bin:  

    for(int i = 0; i 《 30; i++)  



                                                                                             593 


…………………………………………………………Page 595……………………………………………………………

      switch((int)(Math。random() * 3)) {  

        case 0 :  

          bin。addElement(new  

            Aluminum(Math。random() * 100));  

          break;  

        case 1 :  

          bin。addElement(new  

            Paper(Math。random() * 100));  

          break;  

        case 2 :  

          bin。addElement(new  

            Glass(Math。random() * 100));  

      }  

    Vector   

      glassBin = new Vector();  

      paperBin = new Vector();  

      alBin = new Vector();  

    Enumeration sorter = bin。elements();  

    // Sort the Trash:  

    while(sorter。hasMoreElements()) {  

      Object t = sorter。nextElement();  

      // RTTI to show class membership:  

      if(t instanceof Aluminum)  

        alBin。addElement(t);  

      if(t instanceof Paper)  

        paperBin。addElement(t);  

      if(t instanceof Glass)  

        glassBin。addElement(t);  

    }  

    Trash。sumValue(alBin);  

    Trash。sumValue(paperBin);  

    Trash。sumValue(glassBin);  

    Trash。sumValue(bin);  

  }  

} ///:~  

  

要注意的第一个地方是 package 语句:  

package c16。recyclea;  

这意味着在本书采用的源码目录中,这个文件会被置入从 c16 (代表第16 章的程序)分支出来的recyclea 

子目录中。第 17 章的解包工具会负责将其置入正确的子目录。之所以要这样做,是因为本章会多次改写这个 

特定的例子;它的每个版本都会置入自己的“包”(package)内,避免类名的冲突。  

其中创建了几个Vector 对象,用于容纳Trash 句柄。当然,Vector 实际容纳的是 Object (对象),所以它 

们最终能够容纳任何东西。之所以要它们容纳 Trash (或者从Trash 衍生出来的其他东西),唯一的理由是 

我们需要谨慎地避免放入除Trash 以外的其他任何东西。如果真的把某些“错误”的东西置入Vector,那么 

不会在编译期得到出错或警告提示——只能通过运行期的一个违例知道自己已经犯了错误。  

Trash 句柄加入后,它们会丢失自己的特定标识信息,只会成为简单的Object 句柄(上溯造型)。然而,由 

于存在多形性的因素,所以在我们通过Enumeration sorter 调用动态绑定方法时,一旦结果Object 已经造 

型回Trash,仍然会发生正确的行为。sumValue()也用一个Enumeration 对 Vector 中的每个对象进行操作。  

表面上持,先把Trash 的类型上溯造型到一个集合容纳基础类型的句柄,再回过头重新下溯造型,这似乎是 

一种非常愚蠢的做法。为什么不只是一开始就将垃圾置入适当的容器里呢?(事实上,这正是拨开“回收” 

一团迷雾的关键)。在这个程序中,我们很容易就可以换成这种做法,但在某些情况下,系统的结构及灵活 

性都能从下溯造型中得到极大的好处。  



                                                                                         594 


…………………………………………………………Page 596……………………………………………………………

该程序已满足了设计的初衷:它能够正常工作!只要这是个一次性的方案,就会显得非常出色。但是,真正 

有用的程序应该能够在任何时候解决问题。所以必须问自己这样一个问题:“如果情况发生了变化,它还能 

工作吗?”举个例子来说,厚纸板现在是一种非常有价值的可回收物品,那么如何把它集成到系统中呢(特 

别是程序很大很复杂的时候)?由于前面在switch 语句中的类型检查编码可能散布于整个程序,所以每次加 

入一种新类型时,都必须找到所有那些编码。若不慎遗漏一个,编译器除了指出存在一个错误之外,不能再 

提供任何有价值的帮助。  

RTTI 在这里使用不当的关键是“每种类型都进行了测试”。如果由于类型的子集需要特殊的对待,所以只寻 

找那个子集,那么情况就会变得好一些。但假如在一个switch 语句中查找每一种类型,那么很可能错过一个 

重点,使最终的代码很难维护。在下一节中,大家会学习如何逐步对这个程序进行改进,使其显得越来越灵 

活。这是在程序设计中一种非常有意义的例子。  



16。4 改进设计  



 《Design Patterns》书内所有方案的组织都围绕“程序进化时会发生什么变化”这个问题展开。对于任何设 

计来说,这都可能是最重要的一个问题。若根据对这个问题的回答来构造自己的系统,就可以得到两个方面 

的结果:系统不仅更易维护(而且更廉价),而且能产生一些能够重复使用的对象,进而使其他相关系统的 

构造也变得更廉价。这正是面向对象程序设计的优势所在,但这一优势并不是自动体现出来的。它要求对我 

们对需要解决的问题有全面而且深入的理解。在这一节中,我们准备在系统的逐步改进过程中向大家展示如 

何做到这一点。  

就目前这个回收系统来说,对“什么会变化”这个问题的回答是非常普通的:更多的类型会加入系统。因 

此,设计的目标就是尽可能简化这种类型的添加。在回收程序中,我们准备把涉及特定类型信息的所有地方 

都封装起来。这样一来(如果没有别的原因),所有变化对那些封装来说都是在本地进行的。这种处理方式 

也使代码剩余的部分显得特别清爽。  



16。4。1  “制作更多的对象”  



这样便引出了面向对象程序设计时一条常规的准则,我最早是在Grady Booch 那里听说的:“若设计过于复 

杂,就制作更多的对象”。尽管听起来有些暧昧,且简单得可笑,但这确实是我知道的最有用一条准则(大 

家以后会注意到“制作更多的对象”经常等同于“添加另一个层次的迂回”)。一般情况下,如果发现一个 

地方充斥着大量繁复的代码,就需要考虑什么类能使它显得清爽一些。用这种方式整理系统,往往会得到一 

个更好的结构,也使程序更加灵活。  

首先考虑Trash 对象首次创建的地方,这是main()里的一个switch语句:  

  

    for(int i = 0; i 《 30; i++)  

      switch((int)(Math。random() * 3)) {  

        case 0 :  

          bin。addElement(new  

            Aluminum(Math。random() * 100));  

          break;  

        case 1 :  

          bin。addElement (new  

            Paper(Math。random() * 100));  

          break;  

        case 2 :  

          bin。addElement(new  

            Glass(Math。random() * 100));  

      }  

  

这些代码显然“过于复杂”,也是新类型加入时必须改动代码的场所之一。如果经常都要加入新类型,那么 

更好的方案就是建立一个独立的方法,用它获取所有必需的信息,并创建一个句柄,指向正确类型的一个对 

象——已经上溯造型到一个Trash 对象。在《Design Patterns》中,它被粗略地称呼为“创建范式
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!