Builder模式

tbase發表於2004-03-27
將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示.

Builder的目標是從“ 不同的表示”分離出構建過程。這裡,構建過程是必須是相同的,但是產生的結果卻有不同的表現。GoF 指出Builder與Abstract Factory主要的不同在於Builder是step-by-step的,因此構建過程應該是分步驟的。另外,進入Builder的內容應該是連續的物件。

這裡,我仍然是用汽車裝配來舉例(Builder),例如,我的工廠需要裝配3種汽車,他們是貨車,小汽車,和公共汽車。裝配的內容是發動機,輪胎和車廂。他們裝配的次序如下第一步裝配發動機,第二步裝配車廂,第三步裝配輪胎.因為這裡我們有著相同的裝配步驟,但是,結果的表現肯定是不同的,因此我們這裡只可以使用Builder模式,而不是Abstract Factory。

package builder;

import java.util.*;
import junit.framework.*;

//不同的描述
class Automobile extends ArrayList {}
class Car extends Automobile {}
class Truck extends Automobile {}
class Bus extends Automobile {}

// ... 使用的物品
class PartItem {
  private String s;
  public PartItem(String s) { this.s = s; }
  public String toString() { return s; }
}

class Engine extends PartItem {
  public Engine(String s) { super(s); }
}
class Tyre extends PartItem {
  public Tyre(String s) { super(s); }
}
class Carriage extends PartItem {
  public Carriage(String s) { super(s); }
}

// ...各種步驟
class AutoBuilder {
  public void buildBase() {}
  //裝配方法不一樣
  public void addAutomobileItem(PartItem item) {}   //step
  //檢查方法也不一樣
  public void checkAutomobileItem(PartItem item) {} //step
  //都要出去跑兩圈
  public void testAutomobile() {}
  public Automobile getFinishedAutomobile() { return null; }
}

class CarBuilder extends AutoBuilder {
  private Car b;
  public void buildBase() {
    System.out.println("Building Car framework");
    b = new Car();
  }
  public void addAutomobileItem(PartItem part) {
    System.out.println("Adding Car part " + part);
    b.add(part);
  }
  public Automobile getFinishedAutomobile() { return b; }
}

class TruckBuilder extends AutoBuilder {
  private Truck m;
  public void buildBase() {
    System.out.println("Building Truck framework");
    m = new Truck();
  }
  public void addAutomobileItem(PartItem part) {
    System.out.println("Adding part " + part);
    m.add(part);
  }
  public Automobile getFinishedAutomobile() { return m; }
}

class BusBuilder extends AutoBuilder {
  private Bus w;
  public void buildBase() {
    System.out.println("Building Bus framework");
    w = new Bus();
  }
  public void addAutomobileItem(PartItem part) {
    System.out.println("Adding part " + part);
    w.add(part);
  }
  public Automobile getFinishedAutomobile() { return w; }
}

class AutomobileDirector { // "Context"
  private AutoBuilder mb;
  public AutomobileDirector(AutoBuilder mb) {
    this.mb = mb; // Strategy-ish
  }

  //這裡是step-by-step的,不同於Abstract Factory
  public Automobile produceAuto(List input) {
    mb.buildBase();
    for(Iterator it = input.iterator(); it.hasNext();){
      PartItem p  = (PartItem) it.next();
      mb.addAutomobileItem( p);
      mb.checkAutomobileItem(p);
    }
    mb.testAutomobile();
    return mb.getFinishedAutomobile();
  }
};

public class BuildAutomobile extends TestCase {
  private List input = Arrays.asList(new PartItem[] {
    new Engine("Engine"), new Carriage("Carriage"),
    new Tyre("Tyre")
  });

  public void testCar() {
    AutomobileDirector buildCar =
      new AutomobileDirector(new CarBuilder());
    Automobile car = buildCar.produceAuto(input);
    String result = "Car: " + car;
    System.out.println(result);
    assertEquals(result,
      "Car: [Engine, Carriage, Tyre]");
  }
  public void testTruck() {
    AutomobileDirector buildTruck =
      new AutomobileDirector(new TruckBuilder());
    Automobile truck = buildTruck.produceAuto(input);
    String result = "Truck: " + truck;
    System.out.println(result);
    assertEquals(result,
      "Truck: [Engine, Carriage, Tyre]");
  }
  public void testBus() {
    AutomobileDirector buildBus =
      new AutomobileDirector(new BusBuilder());
    Automobile bus = buildBus.produceAuto(input);
    String result = "Bus: " + bus;
    System.out.println(result);
    assertEquals(result,
      "Bus: [Engine, Carriage, Tyre]");
  }
  public static void main(String[] args) {
    junit.textui.TestRunner.run(BuildAutomobile.class);
  }
} ///:~
<p class="indent">

相關文章