2012-12-19 11 views
6

の一部を理解しようとしています。ITEM 40:設計メソッドのシグニチャをEffective Java 2nd Editionから慎重に理解してください。メソッド呼び出しのBuilderパターンを変更する

メソッド署名の可読性を向上させるために提案されていることの1つは、4つ以下のパラメータを目指すことです。より長いパラメータリストは以下の通りであるそのうちの一つの様々な技術を使用して管理することが示唆されている:

最初の二つの側面を組み合わせた第3の技術から ビルダパターン(項目2)を適応させることですオブジェクトの構築からメソッド の呼び出し。 のうちのいくつかがオプションである場合は、特に、すべてのパラメータを表すオブジェクト を定義し、クライアントがこのオブジェクトに対して複数の「セッター」呼び出しを行うようにすると便利ですそれぞれは単一の パラメータまたは小さな関連グループを設定します。目的のパラメータに が設定されると、クライアントはオブジェクトの "execute"メソッドを呼び出します。これは のパラメータの最終的な有効性チェックを行い、実際の の計算を実行します。

オブジェクトの作成に使用されているBuilderパターンはよく知っていますが、メソッド呼び出しにどのように適応させるかを正しく理解しているかどうかは不明です。ここで

は、私がこれまで持っているものです。
(私はmoveメソッドのメソッド呼び出しを改善しようと試みてきた)

public class Space { 

    public static class Builder { 
     // Required parameters 
     private final int x; 
     private final int y; 
     private final int z; 

     // optional params 
     private long time = 0; 

     public Builder(int x, int y, int z) { 
      this.x = x; 
      this.y = y; 
      this.z = z; 
     } 

     public Builder time(long val) { 
      time = val; 
      return this; 
     } 

     public void move() { 
      if (x == 0 || y == 0 || z == 0) { 
       throw new IllegalArgumentException("Cannot move to the centre of the universe"); 
      } 

      // Do the actual work here 
     } 
    } 

// public void move(int x, int y, int z, long time) { 
//  // Do the work here 
// } 

    public static void main(String[] args) { 
     new Builder(1, 1, -1).time(1234).move(); 
    } 
} 

は正しいジョシュアブロッホのアドバイスの私の解釈ですか?

+0

ああ私はそれを行うことを意味しましたが、それは私の心を滑りました。私はjavaのためにjsfiddleのようなものを探したい。 –

+1

完了。ありがとう! –

+0

私は、ビルダービルダー=新しいMoveBuilder()。x(123).y(456).time(789)のようなものを書くことを考えていると思います。 yourObject.execute(builder); ' – assylias

答えて

1

私がやったreifications:流暢ビルダーとファクトリメソッドを使用して。

は、この上の余分な情報と関連する「双方向ビルダー」は、ここを参照してください:http://www.javaworld.com/javaworld/jw-01-2004/jw-0102-toolbox.html?page=3

私は、次のような何かをするだろう。これは恐らく3つの必要なフィールドのためにおそらく過剰ですが、必要なすべてのフィールドを考慮しながら大きなオブジェクトを構築するのに非常に役立ちます。

public Class Space 
{  
    public interface Builder 
    { 
     public Space build(); 
     public int x(); 
     public int y(); 
     public int z(); 
    } 

    // Build a complete Space object accounting for every field. 
    public Space(Space.Builder spaceBuilder) 
    { 
     this.x = spaceBuilder.x(); 
     this.y = spaceBuilder.y(); 
     this.z = spaceBuilder.z(); 
     this.time = builder.time(); 
    } 

    // Might not be necessar if you update time when you update x, y, and z 
    public Builder time(long val) 
    { 
      time = val; 
      return this; 
    } 

    public void move() 
    { 
     // ... 
    } 

    public static void main(String[] args) 
    { 
     new Builder() 
     { 
      @Override 
      public Space build(){ return new Space(this);} 

      @Override 
      public int x(){ return 1;} 

      @Override 
      public int y{ return 1;} 

      @Override int z{ return -1;} 
     }.build().time(1234).move(); 
    } 
} 
2

私はそれを参照してください方法は、あなたのビルダークラス(と同様)、親クラスに関連付けられているだろうし、クライアントがこのようにそれを使用します。

Space space = new Space(); 
... 
Space.MoveBuilder moveBuilder = space.new MoveBuilder(1, 1, -1); 
moveBuilder.setTime(1234); 
moveBuilder.execute(); 

それはさらにによって単純化することができ私はインスタンス化したいクラス内で定義されたインタフェースを使用して、Builderパターンの

space.startMove(1, 1, -1).withTime(1234).endMove(); 
+1

はい、私は非静的なクラスは、それとその囲むクラス間のバインディングを強調することが望ましいことに同意します。 –

0

コンパイル時に、メソッドを呼び出すBuilderを生成するJava Method Invocation Builderを作成しました。また、Javaのメソッド・パラメーターのデフォルト値のサポートも追加されています。

クラスまたはインターフェイスで使用できます。そのタイプに@GenerateMethodInvocationBuilder@Defaultの注釈を追加することによって。

@GenerateMethodInvocationBuilder 
public interface BitBucketServerService { 
@GET("/rest/api/1.0/projects/{projectkey}/repos/{repositoryslug}/pull-requests?direction={direction}&at={at}&state={state}&order={order}&withattributes={withattributes}&withproperties={withproperties}") 
Call<BitbucketServerResponse<BitBucketServerPullRequest>> pullRequests(// 
    @Default("PROJ") @Query("projectkey") String projectKey,// 
    @Default("REPO") @Query("repositoryslug") String repositoryslug,// 
    @Default("INCOMING") @Query("direction") String direction,// 
    @Default("23") @Query("at") String at,// 
    @Default("OPEN") @Query("state") String state,// 
    @Default("NEWEST") @Query("order") String order,// 
    @Default("true") @Query("withattributes") String withattributes,// 
    @Default("true") @Query("withproperties") String withproperties); 
} 

その後、コードがコンパイルされたときにビルダーが生成され、デフォルトのパラメータでそれを呼び出すことができます。

BitBucketServerServicePullRequestsBuilder.pullRequests() 
.invoke(bitBucketServerService); 

それとも、好きなパラメータを設定します。

より上
BitBucketServerServicePullRequestsBuilder.pullRequests() 
.withAt("24") 
.invoke(bitBucketServerService); 

GitHub:https://github.com/tomasbjerre/java-method-invocation-builder

関連する問題