Lombok　②オブジェクトの生成

# Lombok に関する過去記事
[Lombok　①導入編](http://qiita.com/bakira/items/03a7634027e1e98c8c6e)

# オブジェクト生成に関連するアノテーション

## New演算子を使う場合

### 使用アノテーション
- `@NoArgsConstructor`
- `@AllArgsConstructor`

```java:Name.java
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Name
{
    private String value = "";
}
```
```java:Age.java
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Age
{
    private Integer value;
}
```
```java:Person.java
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Person
{
    private Name name = new Name();
    private Age age = new Age();
}
```
```java:PersonFactory.java
public class PersonFactory
{
    public static Person empty()
    {
        return new Person();
    }

    public static Person of( String name, Integer age)
    {
        return new Person(
                   new Name( name ),
                   new Age( age )
               );//コンストラクタの引数はフィールド定義順
    }


}
```

このように生成することが可能です。

## staticメソッドを使う場合

### 使用アノテーション
- `@NoArgsConstructor`
- `@AllArgsConstructor`

```java:Name.java
@NoArgsConstructor(staticName="empty")// staticメソッド名を指定
@AllArgsConstructor(staticName="of")// staticメソッド名を指定
@Data
public class Name
{
    private String value = "";
}
```
```java:Age.java
@NoArgsConstructor(staticName="empty")// staticメソッド名を指定
@AllArgsConstructor(staticName="of")// staticメソッド名を指定
@Data
public class Age
{
    private Integer value;
}
```
```java:Person.java
@NoArgsConstructor(staticName="empty")// staticメソッド名を指定
@AllArgsConstructor(staticName="of")// staticメソッド名を指定
@Data
public class Person
{
    private Name name = Name.empty();
    private Age age = Age.empty();
}
```
```java:PersonFactory.java
public class PersonFactory
{
    public static Person empty()
    {
        return Person.empty();
    }

    public static Person of( String name, Integer age)
    {
        return Person.of(
                  Name.of( name ),
                  Age.of( age )
               );//メソッド引数はフィールド定義順
    }


}
```

このように生成することが可能です。
※この場合、New演算子は**使えなくなる**ので注意。

## builderメソッドを使う場合

### 使用アノテーション
- `@Builder`

Personクラスが以下のように肥大していった場合、

```java:Person.java
@NoArgsConstructor(staticName="empty")
@AllArgsConstructor(staticName="of")
@Data
public class Person
{
    private Name name = Name.empty();
    private Age age = Age.empty();
    private GenderType genderType = GenderType.UNDEFINED;
    private PhoneNumber phoneNumber = PhoneNumber.empty();
    private MailAddress mailAddress = MailAddress.empty();
    ...
}
```

前述の方法だとFactoryクラスが少し複雑になってしまいます。

```java:PersonFactory.java
public class PersonFactory
{
    public static Person empty()
    {
        return Person.empty();
    }

    public static Person of( String name, Integer age, GenderType genderType, String phoneNumber, String mailAddress )
    {
        return Person.of(
                  Name.of( name ),
                  Age.of( age ),
                  genderType,
                  PhoneNumber.of( phoneNumber ),
                  MailAddress.of( mailAddress )
               );//フィールドの順番や数が変化した時に毎回エラーになる
    }
}
```

このようにofメソッドの引数がクラスのフィールド順や数に依存してしまう。

そこで、`@Builder`を追加すると以下のように変わる。

```java:Person.java
@Builder//追加
@AllArgsConstructor(access=AccessLevel.PRIVATE)//通常の引数ありコンストラクタの制御
@NoArgsConstructor(staticName="empty")
@Data
public class Person
{
    private Name name = Name.empty();
    private Age age = Age.empty();
    private GenderType genderType = GenderType.UNDEFINED;
    private PhoneNumber phoneNumber = PhoneNumber.empty();
    private MailAddress mailAddress = MailAddress.empty();
    ...
}
```
```java:PersonFactory.java
public class PersonFactory
{
    public static Person empty()
    {
        return Person.empty();
    }

    public static Person of( String name, Integer age, GenderType genderType, String phoneNumber, String mailAddress )
    {
        return Person.builder（）//bullderの起動
                     .name( Name.of( name ) )//フィールド名のメソッドに対して値をセット
                     .phoneNumber( PhoneNumber.of( phoneNumber ) )//順不同なのでフィールドが入れ替わっても問題無し
                     .mailAddress( MailAddress.of( mailAddress ) )
                     .age( Age.of( age ) )
                     ...
                     .build();//生成

    }
}
```

上記のようにそれなりに柔軟に対応することが可能になります。
ただ、フィールド名を変更した場合はlombokのメソッドまでは修正されないので**手動**でソース修正する必要があります。

また、ここで値をセットしなかったフィールドに対しては**Nullが入る**ので気をつける必要があります。

# 次回

次は各アノテーションの細かい使い方についてまとめようと思います。

じゃあの。