GoF(Gang of Four)のデザインパターン:Factory & Builderパターンを徹底解説
1. はじめに
ソフトウェア開発において、「オブジェクトの作成をどのように管理するか?」 は重要な課題です。
適切な方法を選ばなければ、コードが煩雑になり、再利用性や拡張性が損なわれる 可能性があります。
この問題を解決するために、GoF(Gang of Four)が提唱したデザインパターンの中でも、「Factoryパターン」と「Builderパターン」 は、
オブジェクトの生成を柔軟かつ分かりやすくする方法として広く採用されています。
本記事では、FactoryパターンとBuilderパターンの概要、利点、実装方法(複数言語での実装) を詳しく解説します。
2. Factoryパターン:オブジェクト生成の委譲
2.1. Factoryパターンとは?
Factoryパターン(工場パターン) は、オブジェクトの生成を「Factory(工場)」に委ねることで、コードの柔軟性を向上させる デザインパターンです。
✅ メリット
- クライアント側で new
を直接使用しないため、依存関係が減る
- 生成ロジックを1箇所にまとめることで、拡張しやすい設計になる
- インターフェースを統一できるため、異なる種類のオブジェクトを扱いやすい
❌ デメリット - クラス数が増え、コードが複雑になる - 単純なオブジェクト生成では不要な場合もある
2.2. 各言語でのFactoryパターンの実装
Javaでの実装
// 製品のインターフェース interface Product { void use(); } // 具体的な製品A class ProductA implements Product { public void use() { System.out.println("Product A を使用中"); } } // 具体的な製品B class ProductB implements Product { public void use() { System.out.println("Product B を使用中"); } } // Factory(オブジェクト生成を担うクラス) class ProductFactory { public static Product createProduct(String type) { if (type.equals("A")) { return new ProductA(); } else if (type.equals("B")) { return new ProductB(); } else { throw new IllegalArgumentException("未知の製品タイプ"); } } } // 使用例 public class Main { public static void main(String[] args) { Product product = ProductFactory.createProduct("A"); product.use(); // Output: Product A を使用中 } }
✅ ProductFactory
がオブジェクト生成を管理し、クライアント側は単純なAPIでアクセス可能
Pythonでの実装
class Product: def use(self): pass class ProductA(Product): def use(self): print("Product A を使用中") class ProductB(Product): def use(self): print("Product B を使用中") class ProductFactory: @staticmethod def create_product(product_type): if product_type == "A": return ProductA() elif product_type == "B": return ProductB() else: raise ValueError("未知の製品タイプ") # 使用例 product = ProductFactory.create_product("B") product.use() # Output: Product B を使用中
✅ Pythonでも同様に ProductFactory
がオブジェクト生成を管理する
3. Builderパターン:複雑なオブジェクトの構築
3.1. Builderパターンとは?
Builderパターン(ビルダーパターン) は、
「複雑なオブジェクトの生成過程を、手順ごとに分割して管理する」デザインパターン です。
✅ メリット - 手順を分けて管理できる ため、複雑なオブジェクトの生成が容易 - オブジェクトの不変性(Immutable)を維持 しやすい - オプションのパラメータを柔軟に設定可能
❌ デメリット - 設計がやや複雑 になる - 単純なオブジェクトには不向き
3.2. 各言語でのBuilderパターンの実装
Javaでの実装
class Product { private String partA; private String partB; private Product(Builder builder) { this.partA = builder.partA; this.partB = builder.partB; } public static class Builder { private String partA; private String partB; public Builder setPartA(String partA) { this.partA = partA; return this; } public Builder setPartB(String partB) { this.partB = partB; return this; } public Product build() { return new Product(this); } } public void show() { System.out.println("Product with " + partA + " and " + partB); } } // 使用例 public class Main { public static void main(String[] args) { Product product = new Product.Builder() .setPartA("A") .setPartB("B") .build(); product.show(); // Output: Product with A and B } }
✅ Builderパターンを使うことで、オブジェクトの作成を簡潔に管理できる
Pythonでの実装
class Product: def __init__(self, part_a=None, part_b=None): self.part_a = part_a self.part_b = part_b def show(self): print(f"Product with {self.part_a} and {self.part_b}") class ProductBuilder: def __init__(self): self.product = Product() def set_part_a(self, part_a): self.product.part_a = part_a return self def set_part_b(self, part_b): self.product.part_b = part_b return self def build(self): return self.product # 使用例 builder = ProductBuilder() product = builder.set_part_a("A").set_part_b("B").build() product.show() # Output: Product with A and B
✅ PythonのBuilderパターンも同様に、メソッドチェーンでオブジェクトを構築可能
4. まとめ
項目 | 内容 |
---|---|
Factoryパターンとは? | オブジェクトの生成を「Factory」に委ねることで、コードの柔軟性を向上 |
Factoryのメリット | 依存関係の低減、オブジェクトの生成ロジックを一元管理 |
Builderパターンとは? | 複雑なオブジェクトの生成過程を分離し、メソッドチェーンで管理 |
Builderのメリット | 不変性の維持、オプションパラメータの管理が容易 |
Factoryパターンは「種類ごとのオブジェクトを簡単に生成」 し、
Builderパターンは「複雑なオブジェクトを段階的に構築」 するために有効です。
📌 次回の記事:「GoFの構造パターン(Adapter, Decorator, Facade)」もお楽しみに!
参考資料
バランスよく書かれている。
網羅的に書かれています。骨太。