程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 抽象的應用

抽象的應用

編輯:關於JAVA

走到這一步,接下來該考慮一下設計方案剩下的部分了——在哪裡使用類?既然歸類到垃圾箱的辦法非常不雅且過於暴露,為什麼不隔離那個過程,把它隱藏到一個類裡呢?這就是著名的“如果必須做不雅的事情,至少應將其本地化到一個類裡”規則。看起來就象下面這樣:

現在,只要一種新類型的Trash加入方法,對TrashSorter對象的初始化就必須變動。可以想象,TrashSorter類看起來應該象下面這個樣子:
class TrashSorter extends Vector {
void sort(Trash t) { /* ... */ }
}
也就是說,TrashSorter是由一系列句柄構成的Vector(系列),而那些句柄指向的又是由Trash句柄構成的Vector;利用addElement(),可以安裝新的TrashSorter,如下所示:
TrashSorter ts = new TrashSorter();
ts.addElement(new Vector());
但是現在,sort()卻成為一個問題。用靜態方式編碼的方法如何應付一種新類型加入的事實呢?為解決這個問題,必須從sort()裡將類型信息刪除,使其需要做的所有事情就是調用一個通用方法,用它照料涉及類型處理的所有細節。這當然是對一個動態綁定方法進行描述的另一種方式。所以sort()會在序列中簡單地遍歷,並為每個Vector都調用一個動態綁定方法。由於這個方法的任務是收集它感興趣的垃圾片,所以稱之為grab(Trash)。結構現在變成了下面這樣:

其中,TrashSorter需要調用每個grab()方法;然後根據當前Vector容納的是什麼類型,會獲得一個不同的結果。也就是說,Vector必須留意自己容納的類型。解決這個問題的傳統方法是創建一個基礎“Trash bin”(垃圾筒)類,並為希望容納的每個不同的類型都繼承一個新的衍生類。若Java有一個參數化的類型機制,那就也許是最直接的方法。但對於這種機制應該為我們構建的各個類,我們不應該進行麻煩的手工編碼,以後的“觀察”方式提供了一種更好的編碼方式。
OOP設計一條基本的准則是“為狀態的變化使用數據成員,為行為的變化使用多性形”。對於容納Paper(紙張)的Vector,以及容納Glass(玻璃)的Vector,大家最開始或許會認為分別用於它們的grab()方法肯定會產生不同的行為。但具體如何卻完全取決於類型,而不是其他什麼東西。可將其解釋成一種不同的狀態,而且由於Java有一個類可表示類型(Class),所以可用它判斷特定的Tbin要容納什麼類型的Trash。
用於Tbin的構建器要求我們為其傳遞自己選擇的一個Class。這樣做可告訴Vector它希望容納的是什麼類型。隨後,grab()方法用Class BinType和RTTI來檢查我們傳遞給它的Trash對象是否與它希望收集的類型相符。
下面列出完整的解決方案。設定為注釋的編號(如*1*)便於大家對照程序後面列出的說明。

 

//: RecycleB.java
// Adding more objects to the recycling problem
package c16.recycleb;
import c16.trash.*;
import java.util.*;

// A vector that admits only the right type:
class Tbin extends Vector {
  Class binType;
  Tbin(Class binType) { 
    this.binType = binType; 
  }
  boolean grab(Trash t) {
    // Comparing class types:
    if(t.getClass().equals(binType)) {
      addElement(t);
      return true; // Object grabbed
    }
    return false; // Object not grabbed
  }
}

class TbinList extends Vector { //(*1*)
  boolean sort(Trash t) {
    Enumeration e = elements();
    while(e.hasMoreElements()) {
      Tbin bin = (Tbin)e.nextElement();
      if(bin.grab(t)) return true;
    }
    return false; // bin not found for t
  }
  void sortBin(Tbin bin) { // (*2*)
    Enumeration e = bin.elements();
    while(e.hasMoreElements())
      if(!sort((Trash)e.nextElement()))
        System.out.println("Bin not found");
  }
}

public class RecycleB {
  static Tbin bin = new Tbin(Trash.class);
  public static void main(String[] args) {
    // Fill up the Trash bin:
    ParseTrash.fillBin("Trash.dat", bin);

    TbinList trashBins = new TbinList();
    trashBins.addElement(
      new Tbin(Aluminum.class));
    trashBins.addElement(
      new Tbin(Paper.class));
    trashBins.addElement(
      new Tbin(Glass.class));
    // add one line here: (*3*)
    trashBins.addElement(
      new Tbin(Cardboard.class));

    trashBins.sortBin(bin); // (*4*)

    Enumeration e = trashBins.elements();
    while(e.hasMoreElements()) {
      Tbin b = (Tbin)e.nextElement();
      Trash.sumValue(b);
    }
    Trash.sumValue(bin);
  }
} ///:~


(1) TbinList容納一系列Tbin句柄,所以在查找與我們傳遞給它的Trash對象相符的情況時,sort()能通過Tbin繼承。
(2) sortBin()允許我們將一個完整的Tbin傳遞進去,而且它會在Tbin裡遍歷,挑選出每種Trash,並將其歸類到特定的Tbin中。請注意這些代碼的通用性:新類型加入時,它本身不需要任何改動。只要新類型加入(或發生其他事件)時大量代碼都不需要變化,就表明我們設計的是一個容易擴展的系統。
(3) 現在可以體會添加新類型有多麼容易了。為支持添加,只需要改動幾行代碼。如確實有必要,甚至可以進一步地改進設計,使更多的代碼都保持“固定”。
(4) 一個方法調用使bin的內容歸類到對應的、特定類型的垃圾筒裡。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved