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

“制作更多的對象”

編輯:關於JAVA

這樣便引出了面向對象程序設計時一條常規的准則,我最早是在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》中,它被粗略地稱呼為“創建范式”。要在這裡應用的特殊范式是Factory方法的一種變體。在這裡,Factory方法屬於Trash的一名static(靜態)成員。但更常見的一種情況是:它屬於衍生類中一個被過載的方法。
Factory方法的基本原理是我們將創建對象所需的基本信息傳遞給它,然後返回並等候句柄(已經上溯造型至基礎類型)作為返回值出現。從這時開始,就可以按多形性的方式對待對象了。因此,我們根本沒必要知道所創建對象的准確類型是什麼。事實上,Factory方法會把自己隱藏起來,我們是看不見它的。這樣做可防止不慎的誤用。如果想在沒有多形性的前提下使用對象,必須明確地使用RTTI和指定造型。
但仍然存在一個小問題,特別是在基礎類中使用更復雜的方法(不是在這裡展示的那種),且在衍生類裡過載(覆蓋)了它的前提下。如果在衍生類裡請求的信息要求更多或者不同的參數,那麼該怎麼辦呢?“創建更多的對象”解決了這個問題。為實現Factory方法,Trash類使用了一個新的方法,名為factory。為了將創建數據隱藏起來,我們用一個名為Info的新類包含factory方法創建適當的Trash對象時需要的全部信息。下面是Info一種簡單的實現方式:

 

class Info {
  int type;
  // Must change this to add another type:
  static final int MAX_NUM = 4;
  double data;
  Info(int typeNum, double dat) {
    type = typeNum % MAX_NUM;
    data = dat;
  }
}


Info對象唯一的任務就是容納用於factory()方法的信息。現在,假如出現了一種特殊情況,factory()需要更多或者不同的信息來新建一種類型的Trash對象,那麼再也不需要改動factory()了。通過添加新的數據和構建器,我們可以修改Info類,或者采用子類處理更典型的面向對象形式。
用於這個簡單示例的factory()方法如下:

 

  static Trash factory(Info i) {
    switch(i.type) {
      default: // To quiet the compiler
      case 0:
        return new Aluminum(i.data);
      case 1:
        return new Paper(i.data);
      case 2:
        return new Glass(i.data);
      // Two lines here:
      case 3: 
        return new Cardboard(i.data);
    }
  }


在這裡,對象的准確類型很容易即可判斷出來。但我們可以設想一些更復雜的情況,factory()將采用一種復雜的算法。無論如何,現在的關鍵是它已隱藏到某個地方,而且我們在添加新類型時知道去那個地方。
新對象在main()中的創建現在變得非常簡單和清爽:

 

    for(int i = 0; i < 30; i++)
      bin.addElement(
        Trash.factory(
          new Info(
            (int)(Math.random() * Info.MAX_NUM),
            Math.random() * 100)));


我們在這裡創建了一個Info對象,用於將數據傳入factory();後者在內存堆中創建某種Trash對象,並返回添加到Vector bin內的句柄。當然,如果改變了參數的數量及類型,仍然需要修改這個語句。但假如Info對象的創建是自動進行的,也可以避免那個麻煩。例如,可將參數的一個Vector傳遞到Info對象的構建器中(或直接傳入一個factory()調用)。這要求在運行期間對參數(自變量)進行分析與檢查,但確實提供了非常高的靈活程度。
大家從這個代碼可看出Factory要負責解決的“領頭變化”問題:如果向系統添加了新類型(發生了變化),唯一需要修改的代碼在Factory內部,所以Factory將那種變化的影響隔離出來了。

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