建造者模式


建造者模式


  • 建造者模式也叫作生成器模式,将一个复杂对象的创建与它的表示分离,使得同样的构建过程可以创建不同的表示(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相互独立,有利于系统扩展。
    • 便于控制细节风险由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。
  • 建造者模式的使用场景

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

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

原文地址:https://www.cnblogs.com/zhanglei93/p/6038121.html