builder模式重复参数的初始化?

icnyk63a  于 2021-06-30  发布在  Java
关注(0)|答案(3)|浏览(266)

假设我有一个汽车制造商,它有模型、颜色和速度等参数:

public class Car {

    private String model;
    private int color;
    private int speed;

    public Car(String model, int color, int speed) {
        this.model = model;
        this.color = color;
        this.speed = speed;
    }

    //..Getters

    public static class Builder {
        private String model;
        private int color;
        private int speed;

        public Builder model(String model) {
            this.model = model;
            return this;
        }

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

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

        public Car build() {
            return new Car(model, color, speed);
        }
    }
}

我造的车是这样的:

Car car1 = new Car.Builder()
            .model("Audi")
            .color(Color.RED.getRGB())
            .speed(200)
            .build();
    Car car2 = new Car.Builder()
            .model("Audi")
            .color(Color.RED.getRGB())
            .speed(350)
            .build();
    Car car3 = new Car.Builder()
            .model("Audi")
            .color(Color.RED.getRGB())
            .speed(175)
            .build();

正如你所看到的,我有一些参数需要不断地复制。我希望能够在一些现有空白的基础上制造新车,比如:

Car car1 = new Car.Builder()
            .initFrom(redAudi)
            .speed(200)
            .build();
    Car car2 = new Car.Builder()
            .initFrom(redAudi)
            .speed(350)
            .build();
    Car car3 = new Car.Builder()
            .initFrom(redAudi)
            .speed(175)
            .build();
}

是否有任何模板对此进行了规定?

xdnvmnnf

xdnvmnnf1#

这是一个常见的问题。基本上,你需要暴露一个 asBuilder() . 此示例方法获取一个用传递的示例的值初始化的生成器。

Car existingCar = Car.builder()......build() ;

//new car with same props as existing but the speed
Car existingCarButFaster = existingCar.asBuilder()
                           .speed(existingCar.speed * 2)
                           .build();

实施 asBuilder() 应该直截了当。
而且,您似乎正在生成许多样板文件。如果将代码库与代码生成器连接起来对您来说不是问题,那么可以使用 Lombok 绝大多数项目使用的库。

/**
     * If true, generate an instance method to obtain a builder that is initialized with the values of this instance
     * Legal only if {@code @Builder} is used on a constructor, on the type itself, or on a static method that returns
     * an instance of the declaring type.
     * 
     * @return Whether to generate a {@code toBuilder()} method.
     */
    boolean toBuilder() default false;
ivqmmu1c

ivqmmu1c2#

添加方法 initFrom(Car) 给你的 Builder 类,它调用给定 Car 示例并用返回值初始化其参数。后来对 Builder 的方法可能会用正确的值覆盖这些值。
接下来你可以介绍一个 TemplateCar 类作为新的父类 Car 它允许使用不完整的参数集进行构建,并且有自己的 Builder (当然,您需要将上述方法更改为 initFrom(TemplateCar) ).
这就是你要“模板”的意思吗?

monwx1rj

monwx1rj3#

谢谢你的回答!我决定使用@tquadrat的解决方案,但要扩展一下。我决定为初始化构建器的类添加一个接口。
汽车.java

public class Car {

private final String model;
private final int color;
private final int speed;

public Car(String model, int color, int speed) {
    this.model = model;
    this.color = color;
    this.speed = speed;
}

//..Getters

public static class Builder {
    private String model;
    private int color;
    private int speed;

    public Builder initFrom(@NotNull CarBuilderInitializer initializer) {
        Builder builder = initializer.initBuilder(this);
        this.model = builder.getModel();
        this.color = builder.getColor();
        this.speed = builder.getSpeed();
        return this;
    }

    public Builder model(String model) {
        this.model = model;
        return this;
    }

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

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

    public Car build() {
        return new Car(model, color, speed);
    }
}}

carbuilderinitializer.java文件

public interface CarBuilderInitializer {
    Car.Builder initBuilder(Car.Builder builder);
}

yourcustombuildercar.java

public class YourCustomBuilderCar implements CarBuilderInitializer {
    @Override
    public  initBuilder(@NotNull Car.Builder builder) {
        return builder
                .model("Audi");
                .color(Color.RED);
    }
}

客户端代码:car1=new car.builder().initfrom(new yourcustombuildercar()).speed(200).build();

相关问题