Builderパターンについて

デザインパターンのうちのBuilderパターンを勉強したのでメモしておく。
 

Builderパターンとは

Builderとは、建築者や建築業者などを意味する単語である。
このパターンは複数のコンストラクタを用いて初期化を行いたいような場合に複雑さを抑えることが出来る。
 

Builderパターンを使わない場合の初期化処理

伝統的には、複数のコンストラクタで初期化を行うときには以下のように記述する。

public class foo {
    private int a;
    private int b;
    private int c;

    public foo(a) {
        ……
    }

    public foo(a, b) {
        ……
    }

    public foo(a, b, c) {
        ……
    }
}

 
これはテレスコーピングコンストラクタパターンと呼ばれ、パラメータが増えれば、それに伴ってコンストラクタも増えていくことになる。たった3個のパラメータでは、テレスコーピングコンストラクタパターンはそれほど悪く見えないが、パラメータの数が増えるとすぐに手に負えなくなる。
テレスコーピングコンストラクタパターンは、機能こそするが、多くのパラメータがある場合にはクライアントのコードを書くのが困難になり、そのコードを読むのは更に困難になる。読み手は、パラメータの値が何を意味するかを考えさせられる上に、意味を知るために注意深くパラメータ数を数えなければならない。
 

Builderパターンを使った初期化処理

GoFデザインパターンのBuilderパターン

以下はGoFデザインパターンのBuilderパターンである。

class Dog {
    private String name;
    private Integer age;
    private String hobby;

    String hello() {
        //...
    }
}

class Chihuahua {
    private Builder builder;

    Chihuahua(Builder builder) {
        this.builder = builder;
    }

    void construct() {
        builder.name("Chibi");
        builder.age(3);
        builder.hobby("Dance");
    }
}

interface Builder {
    void name(String name);
    void age(Integer age);
    void hobby(String hobby);

    Dog getResult();
}

class DogBuilder implements Builder {
    private Dog dog;

    DogBuilder() {
        this.dog = new Dog();
    }

    @Override
    public void name(String name) {
        dog.setName(name);
    }
    @Override
    public void age(Integer age) {
        dog.setAge(age);
    }
    @Override
    public void hobby(String hobby) {
        dog.setHobby(hobby);
    }
    @Override
    public Dog getResult() {
        if (dog.getName() == null || dog.getAge() == null) {
            throw new NullPointerException();
        }
        return this.dog;
    }
}

 

Builder builder = new DogBuilder();
Chihuahua chihuahua = new Chihuahua(builder);
chihuahua.construct();
builder.getResult().hello();

 
interfaceや実装など、記述量が多くなるが、Builderの実装クラス(Chihuahua)を切り替えることで、生成するDogの制御が出来る。
 

Effective JavaのBuilderパターン

こちらは、書籍 Effective Javaに載っているBuilderパターンである。

public class Dog {
    private final String  name;
    private final Integer age;
    private final String  hobby;

    public static class Builder {
        //必須パラメータ
        private final String name;

        //オプションパラメータ
        private Integer age;
        private String  hobby;

        public Builder(String name) {
            this.name = name;
        }

        public Builder age(int age) {
            this.age = age;
        }

        public Builder hobby(String hobby) {
            this.hobby = hobby;
        }

        public Dog build() {
            return new Dog(this);
        }
    }

    private Dog(Builder builder) {
        name  = builder.name;
        age   = builder.age;
        hobby = builder.hobby;
    }
}

 

Dog chihuahua = new Dog.Builder("Chibi").age(3).hobby("Dance").build();

 
Builderのセッターメソッドが自身を返すので、呼び出しを連鎖出来る。GoFのBuilderパターンと比べると、記述量が少なく、クライアントからの呼び出しを綺麗に書くことが出来る。
 
 
以上
 
 
参考
書籍 Effective Java
Javaで書くBuilderパターンのパターン – Qiita
7. Builder パターン | TECHSCORE(テックスコア)
10年間Javaを書いていた僕が Effective Java 第2版を読み返して新人に薦められるのかを考えてみた | susumuis Info

Article written by

Comments are closed, but trackbacks and pingbacks are open.