56

有没有什么办法可以在IntelliJ中自动编写生成器模式?IntelliJ中生成器模式代码生成

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

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; 
    } 
} 

是有办法,我能得到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; 
    } 
} 

回答

72

使用Replace Constructor with Builder重构。

要使用此功能,请单击代码中的构造函数签名,然后右键单击并选择“Refactor”菜单,然后单击“Replace Constructor with Builder ...”以调出对话框以生成代码。

+8

有没有办法将“setX()”更改为“withX()”,Serge? – ae6rt 2013-07-18 19:05:04

+2

或者你可以改变setX()为x()吗? – Kurru 2014-03-01 22:29:58

+0

不错!从来没有新的存在。谢谢 – vikingsteve 2014-08-22 06:59:13

9

如果您想知道是否可以使用内部构建器类创建类为described by Joshua Block - 您只需首先定义一个空的内部类,然后选中“使用现有的”并搜索新创建的(内部类)并点击“重构”。

PS!游标必须驻留在构造函数内(预先写好)才能使用“使用Builder替换构造函数”重构函数。

+0

有趣的是,这些插件忘记了构建器模式的重要部分:您仍然应该在构造器中定义所需的参数。否则,您已经从静态捕获缺少的参数错误转移到仅在运行时捕获。 – 2015-06-11 02:44:56

+0

@EJCampbell这将会破坏使用Builder的目的,即通过提供一种将名称附加到参数的方法,使代码更具可读性,即使它们是必需的。这有助于构造函数占用相当多的参数。如果Java允许我们在调用中命名实际参数,比如C#和Swift,那就没有必要。 – ajb 2016-04-07 01:39:22

0

为补充@ CrazyCoder的答案,我认为这是非常有用的知道, 在Replace Constructor with Builder对话框右上侧有一个配置按钮,你可以用它来命名二传手前缀。

13

我发现内置的生成器模式代的IntelliJ是几个原因有点笨重:

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

InnerBuilder plugin解决了所有这些缺点,无需安装或配置。这里有一个插件生成的插件示例:

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); 
     } 
    } 
} 
+2

请参阅[我的答案](http://stackoverflow.com/a/35144261/875485)了解所有提到的问题的内置解决方案。 – jFrenetic 2016-02-02 02:58:34

+0

@jFrenetic提供了一些优点,但我仍然最终发现内置方法太麻烦,即使采用了这些解决方法。使用插件,它实际上就是'alt + shift + B','enter'和BAM,你有你的建造者。 :D – 2016-06-16 18:27:36

+0

OMG这是梦想成真。内置的建设者并没有为我做 - 我更喜欢建设者作为PoJo的内部类。感谢一个可爱的小费! – 2018-01-03 07:29:35

3

对此的IntelliJ方式是,恕我直言,是错综复杂的。这里有两个插件(我更喜欢这个插件:https://plugins.jetbrains.com/plugin/7354),它们的目的要好得多。

例如,我更喜欢将Builder类作为PoJo的内部类。为了用IntelliJ实现这一点,你需要一些额外的笔画。

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

9

这里是如何克服曼苏尔西迪基提到shortcomings

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

这很容易生成。刚刚点击Alt + Ins在Windows上调用生成菜单并选择Constructor

2)这不是快速访问通过“生成”菜单(命令+ N在OS X)

刚去Settings -> Keymap,搜索Builder,并为其赋予一个您选择的快捷方式(如果你经常使用这个功能,这种情况很少发生)。例如,您可以指定Alt + B

另一个替代方案是Ctrl键 + + (查找动作)。开始键入Builder,你会立即得到访问命令:

Find Action dialog

您可以使用此快捷键来快速获得访问任何IntelliJ IDEA的功能(这有很大帮助,当你不记得到底是什么该命令被调用并在哪里找到它)。

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

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

0

对于那些希望用构建器模式替换“太多参数”的用户,先执行“提取参数对象”,然后将转换构造器转换为其他答案中提到的构建器。

0

通过右键单击类Generate> Constructor来生成类的构造函数。然后,在Windows上按下Ctrl + Shift + A来查找动作并输入“builder”,选择 “用构建器替换构造器..”