よく使うJavaライブラリで味わうデザインパターン - Builderパターン


普段よく使うJavaライブラリにも、GoFのデザインパターンが隠されています。日々の作業が忙しく見逃しがちですが、たまにはじっくり一種の芸術ともいえる美しい設計を味わってみましょう。

今回の芸術

import java.util.Locale;
import java.util.Locale.Builder;
...

Locale locale = new Builder()
    .setLanguage("ja")
    .setRegion("JP")
    .setScript("Latn")
    .setExtension(Locale.UNICODE_LOCALE_EXTENSION, "ca-japanese")
    .build();

日時を出力するときなどによく使うJavaのLocaleクラスのインスタンス生成シーンですが、あらためて鑑賞してみると、インターフェイスの美しさにうっとりしてしまいます。

鑑賞のポイント

Localeインスタンスの生成には、Builderクラスが使われています。このクラスのsetXXXメソッドでいろいろなプロパティを設定してから、buildメソッドでインスタンスを生成します。Localeインスタンスがimmutable(不変)であることを予感させるところに美しさを感じます。詳しくは以下で解説します。

Builderパターンを使わない場合

実は、Localeクラスは直接newしてインスタンス化することもできます。むしろ、普通はこっちの書き方をします。こんな感じになります。

// 引数はlanguage, country, variant
Locale locale = new Locale("ja", "JP", "JP");

では、このLocaleインスタンスに新しいプロパティを追加するにはどうすればいいでしょうか?

// XXX: このようなメソッドはない
locale.setScript("Latn");

このようにインスタンスメソッドで設定する方法を思いつくかもしれませんが、こんなメソッドはありません。Localeクラスは、インスタンスが一度作られた後に中身を変えることができないimmutableな設計になっているからです。うっかり別の個所で値が変更されることはないので、安心してインスタンスを使うことができます。

それならば、引数を増やしたコンストラクタを使用するのもひとつの方法でしょう。

// XXX: 引数を4つとるコンストラクタはない
Locale locale = new Locale("ja", "JP", "JP", "Latn");

しかし、このようなコンストラクタはありません。この方法だとコンストラクタの種類がプロパティの数だけ必要になってしまい、プロパティの数が多いクラスを生成するには美しくない実装になってしまいます。

Builderパターンを使った場合

冒頭のコードのようにBuilderパターンを使うことで、以下の恩恵を受けることができます。

1.凝ったオブジェクトを生成できる(今回の場合はimmutableなオブジェクト)
2.オブジェクトへの設定項目が増えても対応できる(今回の場合はクラスのプロパティが増えても引数を増やしたコンストラクタを作る必要がない)

また、

3. buildメソッド内で引数の検証ができる

ということもBuilderパターンの特徴です。ただ、引数の検証は直接newする際のコンストラクタ内でもできるので、今回の比較では関係ありません。

Builderパターンへの賞賛の声

多くの専門家からも、Builderパターンへの賞賛の声が上がっています。

irxgroundさん

複雑なオブジェクトを生成するのに、生成専用のクラスを用意するのは有用である。
http://qiita.com/irxground/items/d1f9cc447bafa8db2388

lang_and_engineさん

あれこれ注文を付けてから,最後にドカンと一発やらかすパターンである。最終的な処理をカスタマイズするために,事前に設定や命令を1個ずつ言い渡す事ができるパターン。とも言える。1個ずつ言い渡せるので,おかげでコンストラクタ内の初期化処理に何もかもを詰め込まないで済む。
http://language-and-engineering.hatenablog.jp/entry/20120330/p1

最後に

わざわざ美術館に行かなくても、たった1行のコードを眺めるだけで知的な愉しみを味わうことができるのは、プログラマーの醍醐味でしょう。

Builderパターンの芸術性に共感してくださったエンジニアの方は、ぜひ当社(クオリサイトテクノロジーズ株式会社)の採用担当までご連絡ください!

関連記事

インスタンスを作る

インターフェイスをシンプルにする

他のクラスに任せる