0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

デザインパターン攻略:Builder編

Posted at

Builderパターンとは?

Builderパターンは、複雑なオブジェクトを段階的に組み立てるための設計パターンです。

例えば、パソコンを組み立てるとき。CPU選んで、メモリ決めて、ストレージ付けて...という感じで、1つずつパーツを組み合わせていきますよね?Builderパターンは、このプロセスをコードで実現するためのパターンなんです。

登場人物

image.png
(wikiより抜粋)

  • Product(生成物): 作りたいオブジェクト本体
  • Builder(ビルダー): オブジェクトの組み立て方を定義するインターフェース
  • ConcreteBuilder(具象ビルダー): 実際に組み立てを行うクラス
  • Director(監督): 組み立ての手順を管理する人(オプション)

メリット

Builderパターンを使うメリットは以下の通りです。

1. 複雑なオブジェクト作りがわかりやすくなる

オブジェクトを作る作業を小さいステップに分けられるので、何をやってるのか分かりやすいです。

2. コンストラクタ地獄から解放される

引数がたくさんあるコンストラクタって、見るだけで避けたくなりますよね... Builderパターンなら、メソッドチェーンで分かりやすく書けます。

// コンストラクタ地獄の例
var pc = new Computer("Intel i9", "32GB", "1TB", "RTX 4080", true, true);

// Builderパターンを使った例
var pc = new ComputerBuilder()
    .SetCPU("Intel i9")
    .SetRAM("32GB")
    .SetStorage("1TB")
    .SetGPU("RTX 4080")
    .AddWiFi()
    .AddBluetooth()
    .Build();

3. 同じ手順で違うものが作れる

Directorで組み立て手順を決めておけば、パーツを変えるだけで色んなバリエーションが作れます。料理のレシピみたいな感じですね☝️

4. 中途半端なオブジェクトができない

Build()を呼ぶまではオブジェクトが完成しないので、「あれ、これ設定し忘れてた!」みたいなミスを防げます。

5. コードが読みやすくなる

何をやってるのか一目瞭然なので、後から見返した時や、他の人がコードを読む時に助かります。機能追加も楽ちんです。

実装してみる

早速実装してみましょう! パソコンを組み立てる例で試してみます。

using System;

// 構築する製品クラス(Product)
public class Computer
{
    public string CPU { get; set; }
    public string RAM { get; set; }
    public string Storage { get; set; }
    public string GPU { get; set; }
    public bool HasWiFi { get; set; }
    public bool HasBluetooth { get; set; }

    public override string ToString()
    {
        return $"Computer: CPU={CPU}, RAM={RAM}, Storage={Storage}, " +
               $"GPU={GPU}, WiFi={HasWiFi}, Bluetooth={HasBluetooth}";
    }
}

// Builderインターフェース
public interface IComputerBuilder
{
    IComputerBuilder SetCPU(string cpu);
    IComputerBuilder SetRAM(string ram);
    IComputerBuilder SetStorage(string storage);
    IComputerBuilder SetGPU(string gpu);
    IComputerBuilder AddWiFi();
    IComputerBuilder AddBluetooth();
    Computer Build();
}

// 具象Builderクラス(ConcreteBuilder)
public class ComputerBuilder : IComputerBuilder
{
    private Computer _computer = new Computer();

    public IComputerBuilder SetCPU(string cpu)
    {
        _computer.CPU = cpu;
        return this;
    }

    public IComputerBuilder SetRAM(string ram)
    {
        _computer.RAM = ram;
        return this;
    }

    public IComputerBuilder SetStorage(string storage)
    {
        _computer.Storage = storage;
        return this;
    }

    public IComputerBuilder SetGPU(string gpu)
    {
        _computer.GPU = gpu;
        return this;
    }

    public IComputerBuilder AddWiFi()
    {
        _computer.HasWiFi = true;
        return this;
    }

    public IComputerBuilder AddBluetooth()
    {
        _computer.HasBluetooth = true;
        return this;
    }

    public Computer Build()
    {
        return _computer;
    }
}

// Director(あらかじめ作成手順を決めておける)
public class ComputerDirector
{
    private IComputerBuilder _builder;

    public ComputerDirector(IComputerBuilder builder)
    {
        _builder = builder;
    }

    // ゲーミングPC構成
    public Computer ConstructGamingPC()
    {
        return _builder
            .SetCPU("Intel Core i9")
            .SetRAM("32GB")
            .SetStorage("1TB SSD")
            .SetGPU("NVIDIA RTX 4080")
            .AddWiFi()
            .AddBluetooth()
            .Build();
    }

    // オフィスPC構成
    public Computer ConstructOfficePC()
    {
        return _builder
            .SetCPU("Intel Core i5")
            .SetRAM("16GB")
            .SetStorage("512GB SSD")
            .AddWiFi()
            .Build();
    }
}

// 使用例
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("=== Builderを直接使用 ===");
        
        // ゲーミングPC
        var gamingPC = new ComputerBuilder()
            .SetCPU("Intel Core i9")
            .SetRAM("32GB")
            .SetStorage("1TB SSD")
            .SetGPU("NVIDIA RTX 4080")
            .AddWiFi()
            .AddBluetooth()
            .Build();

        Console.WriteLine(gamingPC);

        // オフィス用PC
        var officePC = new ComputerBuilder()
            .SetCPU("Intel Core i5")
            .SetRAM("16GB")
            .SetStorage("512GB SSD")
            .AddWiFi()
            .Build();

        Console.WriteLine(officePC);

        Console.WriteLine("\n=== Directorを使用 ===");
        
        // Directorを使った構築
        var director = new ComputerDirector(new ComputerBuilder());
        var gamingPC2 = director.ConstructGamingPC();
        var officePC2 = director.ConstructOfficePC();

        Console.WriteLine(gamingPC2);
        Console.WriteLine(officePC2);
    }
}

実行結果

=== Builderを直接使用 ===
Computer: CPU=Intel Core i9, RAM=32GB, Storage=1TB SSD, GPU=NVIDIA RTX 4080, WiFi=True, Bluetooth=True
Computer: CPU=Intel Core i5, RAM=16GB, Storage=512GB SSD, GPU=, WiFi=True, Bluetooth=False

=== Directorを使用 ===
Computer: CPU=Intel Core i9, RAM=32GB, Storage=1TB SSD, GPU=NVIDIA RTX 4080, WiFi=True, Bluetooth=True
Computer: CPU=Intel Core i5, RAM=16GB, Storage=512GB SSD, GPU=, WiFi=True, Bluetooth=False

まとめ

Builderパターンは、複雑なオブジェクトを作る時にすごく便利なデザインパターンです。コードの可読性と保守性のUPも見込めます!

こんな時にBuilderパターンの利用を検討してみてください💡

  • コンストラクタの引数が多すぎる(4つ以上が目安)
  • オブジェクトを作る手順がややこしい
  • 同じ作り方で色んなバリエーションを作りたい
  • オプション的なパラメータがたくさんある
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?