Builder模式:优先哪一个变量? [关闭](Builder Pattern: which v

2019-07-21 19:25发布

我正想通过有效的Java的书,对我今后的参考创建笔记,我碰到Builder模式。

嗯,我明白它是什么,它是如何假设是used.In的过程中,我创建的生成器模式的两个示例的变化。

我需要在上市下来的差异和优势,每个人都有帮助? 以及我肯定注意到, Example 1通过允许更灵活地使用限制较少和更通用的暴露较少的方法,在那里,在那里。

请指出其他的事情我错过了什么?

实施例1

package item2;

/**
 * @author Sudhakar Duraiswamy
 *
 */
public  class Vehicle {

    private String type;
    private int wheels;

    interface Builder<T>{
        public  T build();
    }

    public static class CarBuilder implements Builder<Vehicle>{
        private String type;
        private int wheels;     

        CarBuilder createVehicle(){
            this.type= "Car";
            return this;
        }

        CarBuilder addWheels(int wheels){
            this.wheels = wheels;
            return this;
        }

        public Vehicle build(){
            Vehicle v = new Vehicle();
            v.type = type;
            v.wheels = wheels;
            return v;
        }               
    }

    public static class TruckBuilder implements Builder<Vehicle>{       
        private String type;
        private int wheels; 

        TruckBuilder createVehicle(){           
            this.type= "Truck";
            return this;
        }

        TruckBuilder addWheels(int wheels){
            this.wheels = wheels;
            return this;
        }

        public Vehicle build(){
            Vehicle v = new Vehicle();
            v.type = type;
            v.wheels = wheels;
            return v;
        }
    }   

    public Vehicle(){

    }

    public static void main(String[] args) {
        //This builds a car with 4 wheels
        Vehicle car = new Vehicle.CarBuilder().createVehicle().addWheels(4).build();

        //THis builds a Truck with 10 wheels
        Vehicle truck = new Vehicle.TruckBuilder().createVehicle().addWheels(10).build();

    }
}

实施例2

package item2;
/**
 * @author Sudhakar Duraiswamy
 *
 */
public  class Vehicle2 {

    private String type;
    private int wheels;

    interface Builder<T>{
        public  T build();      
        public String getType();
        public int getWheels() ;
    }

    public static class CarBuilder implements Builder<Vehicle2>{
        private String type;
        private int wheels;     

        public String getType() {
            return type;
        }
        public int getWheels() {
            return wheels;
        }

        CarBuilder createVehicle(){
            this.type= "Car";
            return this;
        }

        CarBuilder addWheels(int wheels){
            this.wheels = wheels;
            return this;
        }

        public Vehicle2 build(){        
            return new Vehicle2(this);
        }               
    }

    public static class TruckBuilder implements Builder<Vehicle2>{      
        private String type;
        private int wheels; 

        public String getType() {
            return type;
        }

        public int getWheels() {
            return wheels;
        }

        TruckBuilder createVehicle(){           
            this.type= "Truck";
            return this;
        }

        TruckBuilder addWheels(int wheels){
            this.wheels = wheels;
            return this;
        }

        public Vehicle2 build(){
            return new Vehicle2(this);
        }
    }


public Vehicle2(Builder<? extends Vehicle2> builder){
    Vehicle2 v = new Vehicle2();
    v.type = builder.getType();
    v.wheels = builder.getWheels();
}

    public Vehicle2(){
    }

    public static void main(String[] args) {            
        //This builds a car with 4 wheels
        Vehicle2 car = new Vehicle2.CarBuilder().createVehicle().addWheels(4).build();

        //THis builds a Truck with 10 wheels
        Vehicle2 truck = new Vehicle2.TruckBuilder().createVehicle().addWheels(10).build();
    }
}

Answer 1:

以上都不是。

第一个不允许建立一个不可改变的车,这就是为什么经常使用Builder模式。

第二个例子是,其允许从所述构建器使用附加getter方法获取信息的第一个的变体。 但是,这些这些方法没有任何地方使用,除了在汽车的构造,它可以访问直接建设者领域。 我没有看到他们增加点。

我看到两个改善更重要的事情:

  1. 这两种类型的建设者做同样的事情。 有没有必要为两种类型。 中的单独一种是足够的。
  2. 什么createVehicle()方法不应该由制造商构造函数来完成。 如果你构建一个CarBuilder,这显然是造一辆车,所以车辆的类型,应尽快构建构建设置。 这是我会怎么写:

public final class Vehicle {

    private final String type;
    private final int wheels;

    private Vehicle(Builder builder) {
        this.type = builder.type;
        this.wheels = builder.wheels;
    }

    public static Builder carBuilder() {
        return new Builder("car");
    }

    public static Builder truckBuilder() {
        return new Builder("truck");
    }

    public static class Builder {
        private final String type;
        private int wheels;

        private Builder(String type) {
            this.type = type;
        }

        public Builder addWheels(int wheels){
            this.wheels = wheels;
            return this;
        }

        public Vehicle build() {
            return new Vehicle(this);
        }               
    }

    public static void main(String[] args) {
        Vehicle car = Vehicle.carBuilder().addWheels(4).build();
        Vehicle truck = Vehicle.truckBuilder().addWheels(10).build();
    }
}


Answer 2:

还有第三个变种太多,用更少的代码:

相反,有他们自己的实例字段的建设者也可能发生变异的状态Vehicle 。 内部类可以编写自己的外部类的私有成员:

class Vehicle {
  private int wheels;

  private Vehicle() {}

  public static class Builder {
    private boolean building = true;
    private Vehicle vehicle = new Vehicle();

    public Builder buildWheels(int wheels) {
      if(!this.building) throw new IllegalStateException();
      this.vehicle.wheels = wheels;
      return this;
    }

    public Vehicle build() {
      this.building = false;
      return this.vehicle;
    }
  }
}

由于字段是私有,你允许它是建立只有一次building标志),内置Vehicle实例仍然不变的消费者即使字段不能为final了(没有更多realio-trulio不变性 ,见Eric的博客文章是上C#但是概念是相似的)。

你需要更加小心非final字段没有做对象的构造(由编译器执行)期间进行初始化,你必须检查building仔细状态。 你不过保存所有实例字段的一个完整的额外副本。 在一般情况下,如果你有一个相当大的集合,与相当一些方法,每个方法同时建立几个字段建实例变量,这是有用的。

我知道这并没有指出您的做法有什么优势或缺点。 然而,这种方法可以节省大量的额外代码,如果你并不需要的字段是final



文章来源: Builder Pattern: which variant is preferred? [closed]