IntelliJ中的Builder模式代码生成

Mar*_*tyn 76 code-generation design-patterns intellij-idea builder-pattern

有没有办法在IntelliJ中自动编写Builder模式?

例如,给定这个简单的类:

class Film {
   private String title;
   private int length;

   public void setTitle(String title) {
       this.title = title;
   }

   public String getTitle() {
       return this.title;
   }

   public void setLength(int length) {
       this.length = length;
   }

   public int getLength() {
       return this.length;
   }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法,我可以让IDE生成这个或类似的:

public class FilmBuilder {

    Film film;

    public FilmBuilder() {
        film = new Film();
    }

    public FilmBuilder withTitle(String title) {
        film.setTitle(title);
        return this;
    }

    public FilmBuilder withLength(int length) {
        film.setLength(length);
        return this;
    }

    public Film build() {
        return film;
    }
}
Run Code Online (Sandbox Code Playgroud)

Cra*_*der 98

Replace Constructor与Builder重构一起使用.

要使用此功能,请在代码中单击构造函数的签名,然后右键单击并选择"Refactor"菜单,然后单击"使用Builder替换构造函数..."以打开对话框以生成代码.

  • 您可以通过单击"创建构建器"窗口右上角的齿轮并选择"重命名设置器前缀"来更改setter方法的名称.然后您可以将其更改为"with"或完全删除前缀. (14认同)
  • 有没有办法将"setX()"更改为"withX()",Serge? (11认同)
  • 或者你可以将setX()更改为x()吗? (4认同)
  • 是否可以让IntelliJ自动将Builder类创建为内部类? (2认同)
  • 我必须右键单击 +“显示上下文操作”才能在我的 IntelliJ 版本中显示此菜单。 (2认同)

Man*_*qui 21

我发现IntelliJ中的内置构建器模式生成有点笨重,原因如下:

  1. 它需要使用现有的构造函数作为参考.
  2. 它无法通过"生成"菜单快速访问(command+N在OS X上).
  3. 它只生成外部Builder类.正如其他人所提到的,在实现构建器模式时使用静态内部类是很常见的.

InnerBuilder插件解决了所有这些缺点,而且不需要设置或配置.这是一个由插件生成的示例生成器:

public class Person {
    private String firstName;
    private String lastName;
    private int age;

    private Person(Builder builder) {
        firstName = builder.firstName;
        lastName = builder.lastName;
        age = builder.age;
    }

    public static final class Builder {
        private String firstName;
        private String lastName;
        private int age;

        public Builder() {
        }

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

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

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

        public Person build() {
            return new Person(this);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请参阅[我的回答](http://stackoverflow.com/a/35144261/875485),了解所有上述问题的内置解决方案. (3认同)
  • 你提出了一些很好的观点@jFrenetic,但我最终仍然发现内置方法太麻烦,即使有这些解决方法。有了这个插件,实际上只是“alt+shift+B”、“enter”和 BAM,你就拥有了你的构建器。:D (2认同)

jFr*_*tic 15

以下是如何克服Mansoor Siddiqui提到的缺点:

1)它需要使用现有的构造函数作为参考.

这很容易产生.只需在Windows上按Alt+ Ins即可调用Generate菜单并选择Constructor.

2)无法通过"生成"菜单快速访问(OS X上的命令+ N)

只需转到Settings -> Keymap,搜索Builder并为其指定一个您选择的快捷方式(如果您经常使用此功能,这种情况很少见).例如,您可以指定Alt+ B.

另一种选择是Ctrl+ Shift+ A(Find Action).开始输入Builder,您将立即访问该命令:

查找操作对话框

您可以使用此快捷方式快速访问任何IntelliJ IDEA功能(当您不记得命令的确切内容以及在何处找到它时,这会有很大帮助).

3)它只生成外部Builder类.正如其他人所提到的,在实现构建器模式时使用静态内部类是很常见的.

我也更喜欢我的构建器作为静态内部类.不幸的是,没有直接的方法来做到这一点,但它仍然可行.您只需自己定义嵌套的内部类(保持为空),并在调用Replace Constructor with Builder对话框时选择Use existing选项并选择内部类.奇迹般有效!虽然,使这个选项可配置会更容易.


Pål*_*ver 10

如果您想知道这是否可用于创建具有Joshua Block描述的内部构建器类的类- 您只需要先定义一个空的内部类,然后选中"Use existing"并搜索新创建的(内部类) )并点击"重构".

PS!游标必须驻留在构造函数(预编写)中,以便使用"使用Builder替换构造函数"重构函数.


nuc*_*tus 5

IntelliJ的方式是,恕我直言,是令人费解的.有两个插件(我更喜欢这个:https://plugins.jetbrains.com/plugin/7354)更好地服务于目的.

例如,我更喜欢将Builder类作为PoJo的内部类.要使用IntelliJ实现这一目标,您需要额外的笔画.

插件的另一个优点是功能的位置(在Generate...上下文菜单中).


vey*_*kin 5

Lombok 是最简单的方法!(它有一个用于语法支持的 Intellij 插件 https://plugins.jetbrains.com/plugin/6317-lombok-plugin

只需添加一个@Builder注释,它就会在对象内部添加一个构建器实现。

与龙目岛:

import lombok.Builder;
import lombok.Singular;
import java.util.Set;

@Builder
public class BuilderExample {
  @Builder.Default private long created = System.currentTimeMillis();
  private String name;
  private int age;
  @Singular private Set<String> occupations;
}
Run Code Online (Sandbox Code Playgroud)

没有龙目岛:

import java.util.Set;

public class BuilderExample {
  private long created;
  private String name;
  private int age;
  private Set<String> occupations;
  
  BuilderExample(String name, int age, Set<String> occupations) {
    this.name = name;
    this.age = age;
    this.occupations = occupations;
  }
  
  private static long $default$created() {
    return System.currentTimeMillis();
  }
  
  public static BuilderExampleBuilder builder() {
    return new BuilderExampleBuilder();
  }
  
  public static class BuilderExampleBuilder {
    private long created;
    private boolean created$set;
    private String name;
    private int age;
    private java.util.ArrayList<String> occupations;
    
    BuilderExampleBuilder() {
    }
    
    public BuilderExampleBuilder created(long created) {
      this.created = created;
      this.created$set = true;
      return this;
    }
    
    public BuilderExampleBuilder name(String name) {
      this.name = name;
      return this;
    }
    
    public BuilderExampleBuilder age(int age) {
      this.age = age;
      return this;
    }
    
    public BuilderExampleBuilder occupation(String occupation) {
      if (this.occupations == null) {
        this.occupations = new java.util.ArrayList<String>();
      }
      
      this.occupations.add(occupation);
      return this;
    }
    
    public BuilderExampleBuilder occupations(Collection<? extends String> occupations) {
      if (this.occupations == null) {
        this.occupations = new java.util.ArrayList<String>();
      }

      this.occupations.addAll(occupations);
      return this;
    }
    
    public BuilderExampleBuilder clearOccupations() {
      if (this.occupations != null) {
        this.occupations.clear();
      }
      
      return this;
    }

    public BuilderExample build() {
      // complicated switch statement to produce a compact properly sized immutable set omitted.
      Set<String> occupations = ...;
      return new BuilderExample(created$set ? created : BuilderExample.$default$created(), name, age, occupations);
    }
    
    @java.lang.Override
    public String toString() {
      return "BuilderExample.BuilderExampleBuilder(created = " + this.created + ", name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

资料来源: https: //projectlombok.org/features/Builder