- 開発技術
ビルダーパターンはどんな時に使われるか
- #Java
デザインパターンとは
【エンジニア募集中】フルリモート可◎、売上/従業員数9年連続UP、平均残業8時間、有給取得率90%、年休124日以上 etc. 詳細はこちらから>
デザインパターンは、経験豊富なソフトウェア開発者の試行錯誤により得られた、ベストプラクティスです。その中でもGoF(Gang of Four)と呼ばれる4人の共著者によるパターンが特に有名であり、こららのデザインパターンを有効に活用することで開発者に様々なメリットがあります。
デザインパターンにはソフトウェア開発における2つの大きな目的があります。
・エンジニア同士の共通言語
デザインパターンの用語を理解した開発者同士であれば、より容易に互いのアイデアを比較し、議論し合うことが可能です。
・ベストプラクティス
デザインパターンは先人たちの試行錯誤の結晶です。若いエンジニアはデザインパターンを学ぶことで車輪の再発明を行うことなく、素早く優れたコード設計を学ぶことができます。
ビルダーパターンについて
Builderパターンを定義すると、「複雑なオブジェクトの構築をその表現から分離して、同じ構築プロセスで複数の異なる表現を作成できるようにする」ことです。
かなり小難しい表現となってしまいましたが、例えば以下のような場合に役立ちます。
・コンストラクタの引数が多い
・コンストラクタに設定する引数が任意のものが多い
上記の場合を一般的な書き方をするとこうなります(Javaでの記述)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class Hero { String name; String sex; int age; int hp; int mp; int strength; int defense; Hero(String name, String sex, int age, int hp, int mp, int strength, int defense) { if (name == null || sex == null) throw new NullPointerException(); this.name = name; this.sex = sex; this.age = age; this.hp = hp; this.mp = mp; this.strength = strength; this.defense = defense; } } |
インスタンスの生成は以下
1 |
Hero hero = new Hero("太郎", "男性", 25, 100, 150, 80, 120); |
引数が多く、値の受け渡しのミスが多くなってしまいそうです。
また、任意の値も引数として渡さなければならず、記述の無駄が多くなってしまいそうですね。
ビルダーパターン(Effective Java)を利用した場合、インスタンスの生成は以下のようになります。
1 |
Hero hero = new Hero.Builder("太郎", "男性").age().hp(100).stregth(80).build(); |
対象のフィールドを明確に指定できており、わかりやすくなりました。
また、任意のフィールドは設定したい場合のみ記述すればよいのでコードの無駄も減ります。
肝心のビルダーパターンを用いたクラスの記述方法は以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
class Hero { String name; String sex; int age; int hp; int mp; int strength; int defense; static class Builder { private String name; private String sex; private int age; private int hp; private int mp; private int strength; private int defense; Builder(String name, String sex) { this.name = name; this.sex = sex; } Builder age(int age) { this.age = age; return this; } Builder hp(int hp) { this.hp = hp; return this; } Builder mp(int mp) { this.mp = mp; return this; } Builder strength(int strength) { this.strength = strength; return this; } Builder defense(int defense) { this.defense = defense; return this; } People build() { if (name == null || sex == null) { throw new NullPointerException(); } return new Hero(this); } } private Hero(Builder builder) { this.name = builder.name; this.sex = sex; this.age = builder.age; this.hp = builder.hp; this.mp = builder.mp; this.strength = builder.strength; this.defense = builder.defense; } String hello() { //... } } |
static内部クラスを利用して実装しています。
ビルダーパターンのサンプルコード
下記は筆者が実際にビルダーパターンを用いたクラスのインスタンスを生成するコードを書いたときのコードです。
サブスクリプションインスタンスの生成を行っています。
1 2 |
SubscriptionCreateParams subscriptionCreateParams = new SubscriptionCreateParams.Builder().setAutomaticTax(automaticTax) .setCustomer(stripeCustomerObj.getId()).setTrialEnd(trialEnd).addItem(item).build(); |
サブスクリプションには、値段・顧客情報・トライアルの有無など様々なオプションを設定することができ、それぞれの項目が必須なわけではないため、どの項目を設定するかわかりやすくなっています。
上記はビルダーパターンの力を発揮できた例だと言えます。
ビルダーパターンのまとめ
ビルダーパターンを利用すると以下のようなメリットがあります。
・渡すフィールドを明確に指定できるため、可読性が高い。
・任意のフィールド以外は記述する必要がないため、記述の無駄が減る。
ビルダーパターンに関わらず、デザインパターンは上手く利用すると様々なメリットがあります。
【エンジニア募集中】フルリモートも◎(リモート率85.7%)、平均残業8時間、年休124日以上、有給取得率90% etc. 詳細はこちらから>