建造者模式


建造者模式

建造者模式:也叫作生成器模式,将一个复杂对象的创建与它的表示分离,使得同样的构建过程可以创建不同的表示(Separate the construction of a complex object from its representation so that the same construction process can create different representations)。

建造者模式中有4个角色,其通用类图如下:

Product产品类:通常是实现了模板方法模式,也就是有模板方法和基本方法。通常以抽象类和具体类(类图中省略了抽象类)。参考详细例子中的BenzModel和BMWModel类。

Builder抽象建造者:规范产品的组建,定义抽象方法,一般由具体的构建子类实现。详细例子中的CarBuilder就属于抽象建造者。
ConcreteBuilder具体建造者:实现抽象类定义的所有方法,并且返回一个组建好的对象。参见详细例子中的BenBuilder和BMWBuilder。
Director导演类:负责安排已有模板的顺序,然后传递给Builder开始建造。
建造者的通用源码如下:

public class Product {

private void doSomething(){
    //产品的业务处理
}

}

public abstract class Builder {

//设置产品的不同部分,以获得不同的产品
public abstract void setPart();
//建造产品
public abstract Product buildProduct();

}

public class ConcreteBuilder extends Builder{

private Product product = new Product();
@Override
public void setPart() {
    // TODO Auto-generated method stub
    //产品类内部的逻辑处理
}

@Override
public Product buildProduct() {
    // TODO Auto-generated method stub
    return product;
}

}

public class Director {

private Builder builder = new ConcreteBuilder();
public Product getProduct(){
    builder.setPart();
    return builder.buildProduct();
}

}

详细例子的通用类图和源码如下:

public abstract class CarModel {

private ArrayList<String> sequence = new ArrayList<String>();
protected abstract void start();
protected abstract void alarm();
protected abstract void stop();
final public void run(){
    for(int i = 0; i < sequence.size(); i++){
        String actionName = sequence.get(i);
        if(actionName.equalsIgnoreCase("start")){
            this.start();
        }else if(actionName.equalsIgnoreCase("stop")){
            this.stop();
        }else if(actionName.equalsIgnoreCase("alarm")){
            this.alarm();
        }
    }
}
final public void setSequence(ArrayList<String> sequence){
    this.sequence = sequence;
}

}

public class BenzModel extends CarModel{

@Override
protected void start() {
    // TODO Auto-generated method stub
    System.out.println("奔驰车启动");
}
@Override
protected void alarm() {
    // TODO Auto-generated method stub
    System.out.println("奔驰车鸣笛");
}
@Override
protected void stop() {
    // TODO Auto-generated method stub
    System.out.println("奔驰车停止");
}

}

public class BMWModel extends CarModel{

@Override
protected void start() {
    // TODO Auto-generated method stub
    System.out.println("宝马车启动");
}
@Override
protected void alarm() {
    // TODO Auto-generated method stub
    System.out.println("宝马车鸣笛");
}
@Override
protected void stop() {
    // TODO Auto-generated method stub
    System.out.println("宝马车停止");
}

}

public abstract class CarBuilder {

protected abstract void setSequence(ArrayList<String> sequence);
protected abstract CarModel getCarModel();

}

public class BenzBuilder extends CarBuilder{

private BenzModel benz = new BenzModel();
@Override
protected void setSequence(ArrayList<String> sequence) {
    // TODO Auto-generated method stub
    benz.setSequence(sequence);
}
@Override
protected CarModel getCarModel() {
    // TODO Auto-generated method stub
    return this.benz;
}

}

public class BMWBuilder extends CarBuilder{

private BMWModel bmw = new BMWModel();
@Override
protected void setSequence(ArrayList<String> sequence) {
    // TODO Auto-generated method stub
    bmw.setSequence(sequence);
}

@Override
protected CarModel getCarModel() {
    // TODO Auto-generated method stub
    return this.bmw;
}

}

public class Director {

private ArrayList<String> sequence = new ArrayList<String>();
private BenzBuilder benz = new BenzBuilder();
private BMWBuilder bmw = new BMWBuilder();
public BenzModel getBenzModel(){
    this.sequence.clear();
    this.sequence.add("start");
    this.sequence.add("stop");
    benz.setSequence(sequence);
    return (BenzModel)benz.getCarModel();
}
public BMWModel getBMWModel(){
    this.sequence.clear();
    this.sequence.add("start");
    this.sequence.add("alarm");
    this.sequence.add("stop");
    this.bmw.setSequence(sequence);
    return (BMWModel)this.bmw.getCarModel();
}

}

public class Client {

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    Director director = new Director();
    director.getBenzModel().run();
    director.getBMWModel().run();
}

}

View Code

建造者模式的优点

封装性:使用建造者模式可以使客户端不必知道产品内部组成的细节,如例子中我们不必关系每一个具体的模型内部是如何实现的,产生的对象类型就是CarModel。
建造者独立,容易扩展,BenzBuilder和BMWBuilder相互独立,有利于系统扩展。
便于控制细节风险,由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。

建造者模式的使用场景

相同的方法,不同的执行顺序,产生不同的事件结果,可以采用建造者模式;
多个部件或零件都可以装配到一个对象中,但是产生的运行结果又不相同时,则可以使用该模式;
产品类非常复杂,或者产品类中的顺序不同产生不同的效能,则可以使用建造者模式;
在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到时,也可以采用建造者模式封装该对象的创建过程。该种场景只能是一个补偿方法,因为一个对象不容易获得,而在设计阶段竟然没有发觉,而要通过创建者模式柔化创建过程,本身就违反了设计的最初目标。

最佳实践

本文中列举的实例,通过将建造者模式和模板方法模式进行结合,就是一个对建造者模式很好的扩展实践。
 

声明:DungCry.|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 建造者模式


以此热爱,以此谋生。
Le vent se lève, il faut tenter de vivre