84

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

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

12 に答える 12

110

Replace ConstructorwithBuilderリファクタリングを使用します。

この関数を使用するには、コード内のコンストラクターの署名をクリックし、右クリックして[リファクタリング]メニューを選択し、[コンストラクターをビルダーに置き換え...]をクリックしてダイアログボックスを表示し、コードを生成します。

于 2012-04-27T10:23:52.107 に答える
25

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);
        }
    }
}
于 2015-07-15T20:30:17.707 に答える
16

Mansoor Siddiquiが言及した欠点を克服する方法は次のとおりです。

1) 既存のコンストラクターを参照として使用する必要があります。

これは非常に簡単に生成できます。AltWindows で+を押すだけInsで、Generate メニューが呼び出され、 が選択されますConstructor

2) 「生成」メニュー (OS X では command+N) からはすぐにアクセスできません。

に移動しSettings -> Keymap、検索してBuilder、選択したショートカットを割り当てます (この機能を頻繁に使用する場合は、めったにありません)。たとえば、 Alt+を割り当てることができます。B

もう 1 つの選択肢はCtrl+ Shift+ A(検索アクション) です。入力を開始するBuilderと、すぐにコマンドにアクセスできます。

アクションの検索ダイアログ

このショートカットを使用して、IntelliJ IDEA 機能にすばやくアクセスできます (これは、コマンドの名前と場所を正確に覚えていない場合に非常に役立ちます)。

3) 外部 Builder クラスのみを生成します。他の人が言及したように、ビルダー パターンを実装するときに静的内部クラスを使用することは非常に一般的です。

また、ビルダーを静的な内部クラスとして使用することも好みます。残念ながら、それを行う簡単な方法はありませんが、それでも実行可能です。ネストされた内部クラスを自分で定義するだけで (空のままにしておきます)、Replace Constructor with Builderダイアログを呼び出すときに、Use existingオプションを選択して内部クラスを選択します。魔法のように動作します!ただし、このオプションを構成可能にする方が簡単だったでしょう。

于 2016-02-02T02:57:24.803 に答える
12

Joshua Block で説明されているように、これを使用して内部ビルダー クラスを持つクラスを作成できるかどうか疑問に思っている場合は、最初に空の内部クラスを定義する必要があります。次に、[既存のものを使用] をオンにして、新しく作成した (内部クラス) を検索します。 )そして「リファクタリング」を押します。

PS!「コンストラクターをビルダーに置き換える」リファクタリング機能を使用するには、カーソルがコンストラクター (作成済み) 内に存在する必要があります。

于 2014-11-17T12:09:20.367 に答える
5

これに対するIntelliJの方法は、私見ですが、複雑です。目的をはるかによく果たす2つのプラグイン(私はこれが好きです:https://plugins.jetbrains.com/plugin/7354 )があります。

たとえば、私は Builder クラスを PoJo の内部クラスとして持つことを好みます。IntelliJ でそれを実現するには、追加のストロークがほとんど必要ありません。

プラグインのもう 1 つの利点は、機能の場所 (Generate...コンテキスト メニュー内) です。

于 2015-09-14T19:09:58.627 に答える
4

ロンボクはそれを行う最も簡単な方法です! (構文サポート用の 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;
}

ロンボクなし:

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

ソース: https://projectlombok.org/features/Builder

于 2019-01-07T18:04:08.167 に答える
0

「パラメーターが多すぎる」をビルダーパターンに置き換えたい場合は、「パラメーターオブジェクトを抽出」してから、コンストラクターを他の回答で言及されているビルダーに変換します。

于 2016-09-09T17:30:25.647 に答える
0

@CrazyCoderの回答を補完するものとして、コンストラクターをビルダーに置き換えるダイアログの右上に、セッターのプレフィックスの名前を変更するために使用できる構成ボタンがあることを知っておくと非常に便利だと思います。

于 2015-07-09T17:01:05.793 に答える