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」,選擇 「用構建器替換構造器..」