译文

Java设计模式 (二)

翻译:易晓斓 | 2007-08-07 08:30:07 | 阅读2567 | 来源

Builder

定义

一步一步从简单对象建立起复杂对象

何处使用和益处

  • 仅仅明确类型和内容就可以做出一个复杂对象。建成的对象与创建它的细节分开。
  • 将创建一个复杂对象的过程和该对象所包含的组件做接耦化。
  • 将创建和表达的代码分离。
  • 程序员对创建的过程有更好的控制。
  • 相关模式包括:
  • 抽象工厂模式,它主要是集中在工厂模式的层面,也许简单,也许复杂。而一个Builder模式主要用来建立基于简单对象的复杂对象。
  • 复合模式,主要用来建立复杂对象。

举例

比如建一个房子,我们需要这么几步:
1 打基础
2 建框架
3 建室外
4 建室内

让我们用一个抽象类HouseBuilder来定义这四步。任何HouseBuilder类的子类将遵循这四步来建这个房子(也就是说,实施子类里的四个方法)。然后我们用一个WorkShop的类来强制实施这四步的顺序(也就是说,我们必须要在前三步都完成的情况下,才能建室内)。TestBuilder类将用来测试这些类之间的协调性以及检验建房的过程。

import java.util.*;

class WorkShop {
    //force the order of building process
    public void construct(HouseBuilder hb) {
        hb.buildFoundation();
        hb.buildFrame();
        hb.buildExterior();
        hb.buildInterior();
    }
}

//建房的抽象类中定义了建房的4个方法
abstract class HouseBuilder {
    protected House house = new House();
   
    protected String showProgress() {
        return house.toString();
    }

    abstract public void buildFoundation();
    abstract public void buildFrame();
    abstract public void buildExterior();
    abstract public void buildInterior();
}

//建一层房子,注意它的4个方法的具体实施
class OneStoryHouse extends HouseBuilder {
   
    public OneStoryHouse(String features) {
        house.setType(this.getClass() + " " + features);
    }
    public void buildFoundation() {
        //doEngineering()
        //doExcavating()
        //doPlumbingHeatingElectricity()
        //doSewerWaterHookUp()
        //doFoundationInspection()
        house.setProgress("foundation is done");
    }

    public void buildFrame() {
        //doHeatingPlumbingRoof()
        //doElectricityRoute()
        //doDoorsWindows()
        //doFrameInspection()
        house.setProgress("frame is done");
    }

    public void buildExterior() {
        //doOverheadDoors()
        //doBrickWorks()
        //doSidingsoffitsGutters()
        //doDrivewayGarageFloor()
        //doDeckRail()
        //doLandScaping()
        house.setProgress("Exterior is done");
    }

    public void buildInterior() {
        //doAlarmPrewiring()
        //doBuiltinVacuum()
        //doInsulation()
        //doDryWall()
        //doPainting()
        //doLinoleum()
        //doCabinet()
        //doTileWork()
        //doLightFixtureBlinds()
        //doCleaning()
        //doInteriorInspection()
        house.setProgress("Interior is under going");
    }
}

//建两层房子,注意它的4个方法的具体实施和建一层房子的不同
class TwoStoryHouse extends HouseBuilder {
 
    public TwoStoryHouse(String features) {
        house.setType(this.getClass() + " " + features);
    }
    public void buildFoundation() {
        //doEngineering()
        //doExcavating()
        //doPlumbingHeatingElectricity()
        //doSewerWaterHookUp()
        //doFoundationInspection()
        house.setProgress("foundation is done");
    }

    public void buildFrame() {
        //doHeatingPlumbingRoof()
        //doElectricityRoute()
        //doDoorsWindows()
        //doFrameInspection()
        house.setProgress("frame is under construction");
    }

    public void buildExterior() {
        //doOverheadDoors()
        //doBrickWorks()
        //doSidingsoffitsGutters()
        //doDrivewayGarageFloor()
        //doDeckRail()
        //doLandScaping()
        house.setProgress("Exterior is waiting to start");
    }

    public void buildInterior() {
        //doAlarmPrewiring()
        //doBuiltinVacuum()
        //doInsulation()
        //doDryWall()
        //doPainting()
        //doLinoleum()
        //doCabinet()
        //doTileWork()
        //doLightFixtureBlinds()
        //doCleaning()
        //doInteriorInspection()
        house.setProgress("Interior is not started yet");
    }
}

class House {
    private String type = null;
    private List features = new ArrayList();

    public House() {

    }

    public House(String type) {
        this.type = type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }

    public void setProgress(String s) {
        features.add(s);
    }

    public String toString() {
        StringBuffer ff = new StringBuffer();
        String t = type.substring(6);
        ff.append(t + "n ");
        for (int i = 0; i < features.size(); i ++) {
             ff.append(features.get(i) + "n ");
        }
        return ff.toString();
    }
}

class TestBuilder  {
 
    public static void main(String[] args) {
      
       HouseBuilder one = new OneStoryHouse("2 bedrooms, 2.5 baths, 2-car garage, 1500 sqft");
       HouseBuilder two = new TwoStoryHouse("4 bedrooms, 4 baths, 3-car garage, 5000 sqft");

       WorkShop shop = new WorkShop();
       shop.construct(one);
       shop.construct(two);
   
  
       System.out.println("Check house building progress: n");
       System.out.println(one.showProgress());
       System.out.println(two.showProgress());
   }
}


//需要用jdk1.5以上来编译
 
C:> javac TestBuilder.java

C:> java TestBuilder

//运行结果
Check house building progress:

OneStoryHouse 2 bedrooms, 2.5 baths, 2-car garage, 1500 sqft
 foundation is done
 frame is done
 Exterior is done
 Interior is under going

TwoStoryHouse 4 bedrooms, 4 baths, 3-car garage, 5000 sqft
 foundation is done
 frame is under construction
 Exterior is waiting to start
 Interior is not started yet

要更进一步优化上面这个例子的话,每一个doXXX的方法都可以设计成一个类。同样的功能类可以只设计一次,然后被其他类使用,比如,门,窗,厨房等等。

另外,如果要写一个匹萨饼的程序,每一个成分都可以设计成一个类。一个匹萨饼至少包含了几种成分。不同的匹萨饼有不同的成分。这样,我们就可以将Builder的设计模式用上了。

【本文翻译仅为外语学习及阅读目的,原文作者个人观点与译者及译言网无关】

分享:

添加评论