Builder模式

定义

建造模式是对象的创建模式。建造模式可以将一个产品的内部表象(internal representation)与产品的生产过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。

理解

一个复杂对象的表示应该与它的构建过程分离,使得同样的构造过程有着不同的表示。

一些概念

产品的内部表象

  一个产品常有不同的组成成分作为产品的零件,这些零件有可能是对象,也有可能不是对象,它们通常又叫做产品的内部表象(internal representation)。不同的产品可以有不同的内部表象,也就是不同的零件。使用建造模式可以使客户端不需要知道所生成的产品有哪些零件,每个产品的对应零件彼此有何不同,是怎么建造出来的,以及怎么组成产品。

对象性质的建造

  有些情况下,一个对象会有一些重要的性质,在它们没有恰当的值之前,对象不能作为一个完整的产品使用。比如,一个电子邮件有发件人地址、收件人地址、主题、内容、附录等部分,而在最起码的收件人地址得到赋值之前,这个电子邮件不能发送。
  有些情况下,一个对象的一些性质必须按照某个顺序赋值才有意义。在某个性质没有赋值之前,另一个性质则无法赋值。这些情况使得性质本身的建造涉及到复杂的商业逻辑。这时候,此对象相当于一个有待建造的产品,而对象的这些性质相当于产品的零件,建造产品的过程是建造零件的过程。由于建造零件的过程很复杂,因此,这些零件的建造过程往往被“外部化”到另一个称做建造者的对象里,建造者对象返还给客户端的是一个全部零件都建造完毕的产品对象。


    建造模式利用一个导演者对象和具体建造者对象一个个地建造出所有的零件,从而建造出完整的产品对象。建造者模式将产品的结构和产品的零件的建造过程对客户端隐藏起来,把对建造过程进行指挥的责任和具体建造者零件的责任分割开来,达到责任划分和封装的目的。

角色

    抽象建造者(Builder)角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。具体建造者类必须实现这个接口所要求的两种方法:一种是建造方法(buildPart1和 buildPart2),另一种是返还结构方法(retrieveResult)。一般来说,产品所包含的零件数目与建造方法的数目相符。换言之,有多少 零件,就有多少相应的建造方法。
  具体建造者(ConcreteBuilder)角色:担任这个角色的是与应用程序紧密相关的一些类,它们在应用程序调用下创建产品的实例。这个角色要完成的任务包括:1.实现抽象建造者Builder所声明的接口,给出一步一步地完成创建产品实例的操作。2.在建造过程完成后,提供产品的实例。
  导演者(Director)角色:担任这个角色的类调用具体建造者角色以创建产品对象。应当指出的是,导演者角色并没有产品类的具体知识,真正拥有产品类的具体知识的是具体建造者角色。
  产品(Product)角色:产品便是建造中的复杂对象。一般来说,一个系统中会有多于一个的产品类,而且这些产品类并不一定有共同的接口,而完全可以是不相关联的。

UML类图

Java实现

产品product

public class Product {
    /**
     * 定义一些关于产品的操作
     */
    private String part1;
    private String part2;
    public String getPart1() {
        return part1;
    }
    public void setPart1(String part1) {
        this.part1 = part1;
    }
    public String getPart2() {
        return part2;
    }
    public void setPart2(String part2) {
        this.part2 = part2;
    }
}

抽象建造者

public interface Builder {
    public void buildPart1();
    public void buildPart2();
    public Product retrieveResult();
}

具体建造者

public class ConcreteBuilder implements Builder {
    private Product product = new Product();
    /**
     * 产品零件建造方法1
     */
    @Override
    public void buildPart1() {
        //构建产品的第一个零件
     product.setPart1("编号:9527");
    }
    /**
     * 产品零件建造方法2
     */
    @Override
    public void buildPart2() {
        //构建产品的第二个零件
     product.setPart2("名称:XXX");
    }
    /**
     * 产品返还方法
     */
    @Override
    public Product retrieveResult() {
        return product;
    }
}

导演类

public class Director {
    /**
     * 持有当前需要使用的建造器对象
     */
    private Builder builder;
    /**
     * 构造方法,传入建造器对象
     * @param builder 建造器对象
     */
    public Director(Builder builder){
        this.builder = builder;
    }
    /**
     * 产品构造方法,负责调用各个零件建造方法
     */
    public void construct(){
        builder.buildPart1();
        builder.buildPart2();
    }
}

客户端测试

public class Client {
    public static void main(String[]args){
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        director.construct();
        Product product = builder.retrieveResult();
        System.out.println(product.getPart1());
        System.out.println(product.getPart2());
    }
}
    以上是标准的Builder模式,在开发过程中演化出一种简单的Builder模式,那就是没有导演的角色,客户端直接调用builder的build方法来来建造对象,如Android的dialog,如下:
//创建build
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
//向build中set各种建造dialog的"原材料",在代码结构中,这些原材料都是build自带的,但在实际开发中,经常需要传入一些对象来创造不同的产品
builder.setTitle('simple dialog').setIcon(R.drawable.tools).setPositiveButton(builder);
//调用create方法创建对话框
AlertDialog dialog = builder.create();
//显示对话框
dialog.show();
//以上代码可简化为如下形式,在实际开发中我们经常这么用
new AlertDialog.Builder(mContext)..setTitle('simple dialog').setIcon(R.drawable.tools).setPositiveButton(builder).create().show();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章