自动生成Java接口的不可变类和匹配构建器类

时间:2013-02-06 09:43:29

标签: java design-patterns immutability builder-pattern

Java存在哪些工具或库,它们仅使用interface访问器方法定义并自动生成不可变对象类,还有一个“构建器”类,用于通过创建新实例来增量构建新实例或更改现有实例的?

示例输入:

public interface Car {
    String getModelName();
    int getWheelCount();
}

示例输出:

import javax.annotation.concurrent.Immutable;
import javax.annotation.concurrent.NotThreadSafe;

@Immutable
public final class ImmutableCar implements Car {

    @NotThreadSafe
    public static final class Builder implements Car {

        private String modelName;
        private int wheelCount;

        public Builder() {
        }

        public Builder(final Car car) {
            modelName = car.getModelName();
            wheelCount = car.getWheelCount();
        }

        public ImmutableCar build() {
            return new ImmutableCar(wheelCount, modelName);
        }

        @Override
        public String getModelName() {
            return modelName;
        }

        @Override
        public int getWheelCount() {
            return wheelCount;
        }

        public void setModelName(final String modelName) {
            this.modelName = modelName;
        }

        public void setWheelCount(final int wheelCount) {
            this.wheelCount = wheelCount;
        }
    }

    private final String modelName;
    private final int wheelCount;

    public ImmutableCar(final int wheelCount, final String modelName) {
        this.wheelCount = wheelCount;
        this.modelName = modelName;
    }

    @Override
    public String getModelName() {
        return modelName;
    }

    @Override
    public int getWheelCount() {
        return wheelCount;
    }

}

5 个答案:

答案 0 :(得分:3)

Google有一个名为AutoValue的工具可以执行此操作,除非基于抽象基类而不是接口。

import com.google.auto.value.AutoValue;

class Example {
  @AutoValue
  abstract static class Animal {
    static Builder builder() {
      return new AutoValue_Example_Animal.Builder();
    }

    abstract String name();
    abstract int numberOfLegs();

    @AutoValue.Builder
    abstract static class Builder {
      abstract Builder name(String s);
      abstract Builder numberOfLegs(int n);
      abstract Animal build();
    }
  }
}

另一个类似的工具是Immutables;这可能是与问题更接近的匹配,因为它使用接口并生成不可变的实现和构建器。

答案 1 :(得分:2)

Lombok允许这样的代码:

@lombok.Data
@lombok.Builder
public class ImmutableCar implements Car {
    private final @lombok.NonNull String modelName;
    private final @lombok.NonNull int wheelCount;
}

在编译时处理lombok注释(JSR-269)以生成完整的类。也可以通过' delomboking'来查看生成的代码。通过Maven插件。

答案 2 :(得分:1)

查看Eclipse Model2Text project及其子项目,尤其是AcceleoXpand。它们通常用于为EMF模型生成基于EMF的Java代码,但它们也可用于生成简单的POJO。

但是这个功能并不是开箱即用的:你必须为它创建自己的代码生成器和模板。见Accelelo tutorial

编辑:

还有一个想法 - 一个如此简单,以至于我花了一天才意识到它

您可以使用VelocityFreemarker或类似的模板库(通常用于生成html)。虽然你仍然需要在某个地方创建一个模型,例如.txt或.xml文件。这是一个tutorial on Velocity code generation

答案 3 :(得分:1)

我刚创建了一个eclipse插件https://github.com/karajdaar/templator

它基于Freemarker模板生成代码。 Freemarker模板的上下文是ICompilationUnit,它允许完全访问命名类及其信息。我们正在使用它为NoSQL数据库,球衣客户端,测试等生成DAO。

我认为这很容易做到这里所需要的。

答案 4 :(得分:1)

Immutables(http://immutables.github.io)注释处理器完全符合您的需求。它功能齐全且可定制(你知道所有set vs with vs无前缀战争, - 使用你喜欢的任何东西)。它可以使用接口,抽象类,注释的构建器生成不可变的实现。此外,它还可以生成构建器以调用静态工厂方法或POJO构造函数以及许多其他内容。

@Value.Immutable
public interface ValueObject {
  String name();
  List<Integer> counts();
  Optional<String> description();
}

// Compile using annotation processor and use it like this
ValueObject valueObject =
   ImmutableValueObject.builder()
      .name("My value")
      .addCounts(1)
      .addCounts(2)
      .build();