面向对象:建造者(Builder)模式

以下内容来自http://www.lifevv.com/sysdesign/index.html

 本文介绍设计模式中的建造者(Builder)模式的概念,用法,以及实际应用中怎么样使用Builder模式进行开发。

Builder模式的概念

Builder模式是一种对象创建型模式,它跟工厂模式(包括工厂方法模式与虚拟工厂模式)一样,都用来创建类的对象。我们先阐述一下Builder模式的定义
Builder模式用来创建复合对象,并把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象;另一方面,为了统一创建过程,又把对象创建的操作统一封装在名为Director所提供的方法里。
复合对象的概念:
所 谓复合对象,指有别于一般的对象,该对象具有不同的复合属性。比如我们把一辆汽车看成一个复合对象,是因为该汽车由多个复杂的零部件组成,这些零部件可能 因为生产厂家的不同等等而不同,但这些不同的零部件最终都能被组装为一辆汽车。这些不同的零部件我们可称之为汽车的复合属性,同样可称该汽车为一个复合对 象。

我们再用类图来说明Builder模式的结构,如图:

[该图出自维基百科wikipedia.org]

图示,
- Builder#buildPart方法(不同部分的创建都是一个buildPart方法)用来创建产品Product的各部分;
- ConcreteBuilder为继承自Builder的具体的创建类;
- Builder#getResult或ConcreteBuilder#getResult返回最终被创建的复合对象;
- Product为被创建的产品对象;
- Director#construct方法是对整个产品创建过程的封装;该方法内部将调用Builder#buildPart方法;一个典型的construct方法实现可能为:
public void construct(Builder builder) {
    builder.buildPart1();
    builder.buildPart2();
    ...
}
有时为了简便,又可把Director与ConcreteBuilder合并为一个类。

Builder模式与工厂模式的区别与Builder模式的应用场景

我们上面提到了,Builder模式和工厂模式一样,都属于对象创建型模式,都用来创建类的对象。但它们存在在本质的区别:
- 在工厂模式里,我们无需关心产品的各部分是如何被创建的;但在Builder模式里,会把产品的创建过程抽象为多个部分。也就是说,工厂模式被关注的是整个产品,而Builder模式被关注的是产品的组成部分的创建过程。
- 因为上述关注点的不一样,工厂模式被创建的产品是一个单一产品;Builder模式创建的是一个复合产品。

简单一点说,在具体的应用中,我们是选用工厂模式来创建对象呢还是选用Builder模式来创建对象,完全取决于我们的关注点。
比如同为创建一辆汽车,如果我们只需关注只是从工厂里造出的这一辆汽车本身(然后加以使用),我们就可以使用工厂模式来创建该汽车;但如果我们还应该关注该汽车的各部分是怎么造出来的(或者说,不同的工厂对产品的各部分的造法不一样),我们就应该使用Builder模式。

 

Builder模式的应用场景
- 对象的创建:Builder模式是为对象的创建而设计的模式
- 创建的是一个复合对象:被创建的对象为一个具有复合属性的复合对象
- 关注对象创建的各部分的创建过程:不同的工厂(这里指builder生成器)对产品属性有不同的创建方法

Builder模式的应用范例

下面我们举个例子来加深我们对Builder模式的理解。
比如我们要通过一个汽车加工厂,组装一辆汽车;汽车由车头,车身,车尾3部分组成;它的基本组装步骤是:
- 组装车头
- 组装车身
- 组装车尾

不管被组装的是吉普车,卡车,还是公交车,它们都可以各自重新定义车头,车身与车尾的组装方法;而通过这些被重新定义的组装方法,通过相同的组装步骤就可以组装具有不同属性的各类汽车了。
通过上面的分析,我们知道,该范例满足Builder模式的应用场景所提到的条件:
- 对象的创建:我们需要创建汽车对象
- 创建的是一个复合对象:我们需要创建的汽车对象是具有车头,车身,车尾等复合属性的复合对象
- 关注对象创建的各部分的创建过程:吉普车,卡车等对车头,车身,车尾的组装方法不尽相同


下面我们用Builder设计模式来抽象以上组装过程:
- CarDirector:汽车组装操作的封装类
- CarBuilder:汽车组装抽象类
- JeepBuilder:吉普车组装类,继承自CarBuilder类。
- Car:汽车类,包括车头,车身,车尾等属性。相当于产品类。由CarBuilder/JeepBuilder等创建。

源代码

<script src="http://www.lifevv.com/images/code/js/shCore.js" type="text/javascript"></script> <script> <!--// function _syboos_pmplat_setUpCode() { //dp.SyntaxHighlighter.ClipboardSwf = 'js/clipboard.swf'; dp.SyntaxHighlighter.HighlightAll('_syboos_pmplat_code'); } window.οnlοad=_syboos_pmplat_setUpCode; //--> </script> <script src="http://www.lifevv.com/images/code/js/shBrushJava.js" type="text/javascript"></script>
  1. //汽车类   
  2. public   class  Car {  
  3.     //车头   
  4.     private  String head;  
  5.     //车身   
  6.     private  String body;  
  7.     //车尾   
  8.     private  String tail;  
  9.   
  10.     public  String getBody() {  
  11.         return  body;  
  12.     }  
  13.     public   void  setBody(String body) {  
  14.         this .body = body;  
  15.     }  
  16.     public  String getHead() {  
  17.         return  head;  
  18.     }  
  19.     public   void  setHead(String head) {  
  20.         this .head = head;  
  21.     }  
  22.     public  String getTail() {  
  23.         return  tail;  
  24.     }  
  25.     public   void  setTail(String tail) {  
  26.         this .tail = tail;  
  27.     }  
  28. }  
  29.   
  30.   
  31. //汽车组装抽象类   
  32. public   abstract   class  CarBuilder {  
  33.     //组装车头   
  34.     public   abstract   void  makeHead();  
  35.     //组装车身   
  36.     public   abstract   void  makeBody();  
  37.     //组装车尾   
  38.     public   abstract   void  makeTail();  
  39.     //得到被组装好的汽车对象   
  40.     public   abstract  Car getCar();  
  41. }  
  42.   
  43. //吉普车组装类   
  44. public   class  JeepBuilder  extends  CarBuilder {  
  45.     Car car = new  Car();  
  46.   
  47.     //组装车头   
  48.     public   void  makeHead() {  
  49.         car.setHead("Jeep head" );  
  50.     }  
  51.     //组装车身   
  52.     public   void  makeBody() {  
  53.         car.setHead("Jeep body" );  
  54.     }  
  55.     //组装车尾   
  56.     public   void  makeTail() {  
  57.         car.setHead("Jeep tail" );  
  58.     }  
  59.   
  60.     public  Car getCar() {  
  61.         return  car;  
  62.     }  
  63. }  
  64.   
  65.   
  66. //汽车组装操作的封装类:该类封装了对整个汽车的组装操作   
  67. public   class  CarDirector {  
  68.     //汽车的组装操作   
  69.     public   void  makeCar(CarBuilder builder) {  
  70.         //组装车头   
  71.         builder.makeHead();  
  72.         //组装车身   
  73.         builder.makeBody();  
  74.         //组装车尾   
  75.         builder.makeTail();  
  76.     }  
  77. }  
  78.   
  79. //调用   
  80. public   class  Client {  
  81.     public   static   void  main(String[] args) {  
  82.         CarDirector director = new  CarDirector();  
  83.   
  84.         //创建吉普车生成器(工厂)   
  85.         CarBuilder b = new  JeepBuilder();  
  86.         //调用CarDirector组装整个汽车   
  87.         director.makeCar(b);  
  88.   
  89.         //得到组装好的汽车   
  90.         Car car = b.getCar();  
  91.         System.out.println(car.getHead());  
  92.         System.out.println(car.getBody());  
  93.         System.out.println(car.getTail());  
  94.     }  
  95. }  
//汽车类
public class Car {
    //车头
    private String head;
    //车身
    private String body;
    //车尾
    private String tail;

    public String getBody() {
        return body;
    }
    public void setBody(String body) {
        this.body = body;
    }
    public String getHead() {
        return head;
    }
    public void setHead(String head) {
        this.head = head;
    }
    public String getTail() {
        return tail;
    }
    public void setTail(String tail) {
        this.tail = tail;
    }
}


//汽车组装抽象类
public abstract class CarBuilder {
    //组装车头
    public abstract void makeHead();
    //组装车身
    public abstract void makeBody();
    //组装车尾
    public abstract void makeTail();
    //得到被组装好的汽车对象
    public abstract Car getCar();
}

//吉普车组装类
public class JeepBuilder extends CarBuilder {
    Car car = new Car();

    //组装车头
    public void makeHead() {
        car.setHead("Jeep head");
    }
    //组装车身
    public void makeBody() {
        car.setHead("Jeep body");
    }
    //组装车尾
    public void makeTail() {
        car.setHead("Jeep tail");
    }

    public Car getCar() {
        return car;
    }
}


//汽车组装操作的封装类:该类封装了对整个汽车的组装操作
public class CarDirector {
    //汽车的组装操作
    public void makeCar(CarBuilder builder) {
        //组装车头
        builder.makeHead();
        //组装车身
        builder.makeBody();
        //组装车尾
        builder.makeTail();
    }
}

//调用
public class Client {
    public static void main(String[] args) {
        CarDirector director = new CarDirector();

        //创建吉普车生成器(工厂)
        CarBuilder b = new JeepBuilder();
        //调用CarDirector组装整个汽车
        director.makeCar(b);

        //得到组装好的汽车
        Car car = b.getCar();
        System.out.println(car.getHead());
        System.out.println(car.getBody());
        System.out.println(car.getTail());
    }
}



运行并显示Client:

C:/builder>javac *.java
C:/builder>java Client
Jeep head
Jeep body
Jeep tail
C:/builder>


上面演示了吉普车(Jeep)的生产过程,如果需要创建公交车(Bus),我们可以依葫芦画瓢,使用一个继承自CarBuilder的BusBuilder,便可简单地生产一个具有与吉普车不同的车头,车身,车尾的汽车来。

Builder模式与Template Method模式的区别

我们在
设计模式之Template Method - 模板方法模式
一文中对Template Method模式作了介绍,细心的读者可能会发现,这2种模式中我们举了有点类似的范例:通过汽车加工厂组装汽车(车头,车身,车尾)来说明这2种模式。
但他们之间存在本质的区别:
- Template Method模式只是继承的关系,Builder模式与Factory Method模式一样,除了继承之外,还有有创建的过程。
- Template Method模式强调的是操作(固定的步骤操作与不同的算法细节),而Builder模式除了强调动作(创建对象的各部分)之外,还强调了整个对象的生 成。这是他们之间的本质区别,Builder模式是一种对象创建型设计模式,Template Method是动作型模式。

Builder模式小结

Builder模式是一种注重对象创建细节的设计模式,它被用来动态创建复合对象。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值