Skip to content

Commit 1b4bd03

Browse files
committed
ブログ追加
1 parent d40f100 commit 1b4bd03

1 file changed

Lines changed: 231 additions & 0 deletions

File tree

WebSite/content/blog/blog_00029.md

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
---
2+
title: GoFデザインパターン - ファクトリメソッド編
3+
date: 2026-01-27
4+
category: Coding
5+
description: GoFコレクションにおけるファクトリメソッドパターン実践ガイド:概念、使いどころ、C++/Python の実装例、注意点と出典を実用的に解説します
6+
tags: [Coding, DesignPattern]
7+
recommended: true
8+
thumbnail: assets/img/ogp.png
9+
---
10+
11+
こんにちは!パン君です。
12+
13+
今回は GoF(Gang of Four)のデザインパターンのファクトリメソッド編になります。
14+
サンプルコード(C++)、作り方、使うタイミング、注意点などを含めて実用的に解説します。
15+
16+
## はじめに
17+
18+
ファクトリメソッドはサブクラスが生成する具体的なクラスを決定するためのメソッドを提供するデザインパターンです。
19+
言い換えると、オブジェクト生成の責務をサブクラスに委譲することで、クライアントコードは具体的な実装に依存せずに動作できます。
20+
21+
Wikipedia の定義は下記です
22+
23+
> "オブジェクト指向プログラミングにおいて、ファクトリメソッドパターンは作成されるオブジェクトの正確なクラスを指定せずにオブジェクトを作成する問題に対処するためにファクトリメソッドを使用する生成パターンである。"
24+
> (出典: [https://en.wikipedia.org/wiki/Factory_method_pattern](https://en.wikipedia.org/wiki/Factory_method_pattern)
25+
26+
上記はファクトリメソッドの本質を端的に示しています
27+
生成の「いつ」「どのクラスを」決めるかを実行時の文脈やサブクラスの実装に委ねる、ということです。
28+
29+
## 構造(要素)
30+
31+
典型的な構成は次の通りです。
32+
33+
- `Product`(抽象製品):クライアントが扱う共通インターフェース
34+
- `ConcreteProduct`:具体的な製品の実装
35+
- `Creator`(抽象作成者):`FactoryMethod()` を宣言(場合によっては一部の共通処理も持つ)。
36+
- `ConcreteCreator``FactoryMethod()` をオーバーライドし、具体的な `ConcreteProduct` を生成して返す。
37+
38+
`Creator` は生成された `Product` を使って何らかの処理を行い、クライアントは `Creator` の操作だけを利用します。
39+
40+
```mermaid
41+
classDiagram
42+
class Product {
43+
<<interface>>
44+
+Use()
45+
}
46+
47+
class ConcreteProductA
48+
class ConcreteProductB
49+
Product <|-- ConcreteProductA
50+
Product <|-- ConcreteProductB
51+
52+
class Creator {
53+
<<abstract>>
54+
+FactoryMethod() Product
55+
+Operation()
56+
}
57+
58+
class ConcreteCreatorA
59+
class ConcreteCreatorB
60+
Creator <|-- ConcreteCreatorA
61+
Creator <|-- ConcreteCreatorB
62+
63+
ConcreteCreatorA ..> ConcreteProductA : creates
64+
ConcreteCreatorB ..> ConcreteProductB : creates
65+
```
66+
67+
## 短いメリット / デメリット
68+
69+
メリット:
70+
- 生成ロジックと利用ロジックを分離できる。
71+
- 新しい `ConcreteProduct` を追加しても既存のクライアントコードを変更せずに済む(拡張に対して開かれている)。
72+
- テスト時に `Creator` を差し替えることで生成される型を制御できる(モック生成など)。
73+
74+
デメリット:
75+
- サブクラスが増えるとクラス数が増える(サブクラス増加による管理コスト)。
76+
- 単純なケースでは過剰な抽象化になることがある(過剰設計)。
77+
- 生成の決定が分散することで設計を追うのが難しくなる場合がある。
78+
79+
## 「シンプルファクトリ」「抽象ファクトリ」との違い(整理)
80+
81+
- `Simple Factory`: ファクトリ関数/クラスが条件分岐で具体クラスを返す単純な実装。GoF の正式なパターンではないがよく使われる。
82+
- `Factory Method`: サブクラス化により生成クラスを決定する。生成ロジックはオブジェクト指向の多態性で拡張される。
83+
- `Abstract Factory`: 関連する複数のオブジェクト群(製品族)を生成するためのインターフェースを提供する。製品群の整合性を保つ。
84+
85+
選択基準の目安:
86+
- 単一の製品を生成し、サブクラスごとに生成方法を変えたい → `Factory Method`
87+
- 関連する複数の製品群(例:UI ウィジェットのテーマ一式)をまとめて切り替えたい → `Abstract Factory`
88+
89+
## 実装例:C++(典型)
90+
91+
以下は最小限の C++ サンプルです。`Creator``FactoryMethod()` を宣言しており、`ConcreteCreator` が具体生成を行います。
92+
93+
```cpp
94+
// Product.h
95+
class Product {
96+
public:
97+
virtual ~Product() = default;
98+
virtual const char* Use() const = 0;
99+
};
100+
101+
// ConcreteProductA.h
102+
#include "Product.h"
103+
class ConcreteProductA : public Product {
104+
public:
105+
const char* Use() const override { return "ConcreteProductA"; }
106+
};
107+
108+
// ConcreteProductB.h
109+
#include "Product.h"
110+
class ConcreteProductB : public Product {
111+
public:
112+
const char* Use() const override { return "ConcreteProductB"; }
113+
};
114+
115+
// Creator.h
116+
#include <memory>
117+
class Creator {
118+
public:
119+
virtual ~Creator() = default;
120+
// Factory Method(生成をサブクラスに委譲)
121+
virtual std::unique_ptr<Product> FactoryMethod() const = 0;
122+
123+
// Creator は生成された Product を使う共通処理を持てる
124+
std::string Operation() const {
125+
auto product = FactoryMethod();
126+
return std::string("Creator uses ") + product->Use();
127+
}
128+
};
129+
130+
// ConcreteCreatorA.h
131+
#include "Creator.h"
132+
#include "ConcreteProductA.h"
133+
class ConcreteCreatorA : public Creator {
134+
public:
135+
std::unique_ptr<Product> FactoryMethod() const override {
136+
return std::make_unique<ConcreteProductA>();
137+
}
138+
};
139+
140+
// ConcreteCreatorB.h
141+
#include "Creator.h"
142+
#include "ConcreteProductB.h"
143+
class ConcreteCreatorB : public Creator {
144+
public:
145+
std::unique_ptr<Product> FactoryMethod() const override {
146+
return std::make_unique<ConcreteProductB>();
147+
}
148+
};
149+
150+
// main.cpp (利用例)
151+
#include <iostream>
152+
int main() {
153+
ConcreteCreatorA a;
154+
ConcreteCreatorB b;
155+
std::cout << a.Operation() << "\n"; // Creator uses ConcreteProductA
156+
std::cout << b.Operation() << "\n"; // Creator uses ConcreteProductB
157+
}
158+
```
159+
160+
この実装のポイントは、`Creator` の `Operation()` は具体的な `Product` のクラスを知らずに動作する点です。`ConcreteCreator` を差し替えるだけで動作が変わります。
161+
162+
## 実装例:Python(簡潔)
163+
164+
動的言語では実装がさらに簡潔になります。サブクラスで `factory_method` をオーバーライドします。
165+
166+
```python
167+
from abc import ABC, abstractmethod
168+
169+
class Product(ABC):
170+
@abstractmethod
171+
def use(self) -> str:
172+
pass
173+
174+
class ConcreteProductA(Product):
175+
def use(self) -> str:
176+
return "ConcreteProductA"
177+
178+
class ConcreteProductB(Product):
179+
def use(self) -> str:
180+
return "ConcreteProductB"
181+
182+
class Creator(ABC):
183+
@abstractmethod
184+
def factory_method(self) -> Product:
185+
pass
186+
187+
def operation(self) -> str:
188+
product = self.factory_method()
189+
return f"Creator uses {product.use()}"
190+
191+
class ConcreteCreatorA(Creator):
192+
def factory_method(self) -> Product:
193+
return ConcreteProductA()
194+
195+
class ConcreteCreatorB(Creator):
196+
def factory_method(self) -> Product:
197+
return ConcreteProductB()
198+
199+
if __name__ == "__main__":
200+
a = ConcreteCreatorA()
201+
b = ConcreteCreatorB()
202+
print(a.operation()) # Creator uses ConcreteProductA
203+
print(b.operation()) # Creator uses ConcreteProductB
204+
```
205+
206+
Python の場合、型チェックや依存関係注入を組み合わせてテストを容易にできます。
207+
208+
## 実務上の注意点(影響範囲の確認を必ず行う)
209+
210+
- 影響範囲: `Creator` を拡張すると生成される `Product` の種類が増えるため、関連テスト・ドキュメント・ビルド影響を確認してください。特にシリアライズや API 境界で生成される型が変わると互換性影響が出ます。
211+
- 曖昧さの回避: 「生成はどこで決まるか」を明確にし、責務をドキュメント化してください。生成ロジックが分散すると可読性が落ちます。
212+
- テスト性: `Creator` をテスト用に差し替えられるように設計すると良い(テスト専用 `ConcreteCreator` の用意、または依存注入で `factory` を注入)。
213+
- スタティックファクトリとの併用: 言語によっては静的ファクトリ関数やコンストラクタ注入で十分なケースもあります。パターン導入のコストと利得を比較してください。
214+
- 不要な抽象化を避ける: シンプルな条件分岐で十分な場合は `Simple Factory` を選ぶのも現実的です。
215+
216+
## まとめ
217+
218+
- `Factory Method` は生成責務をサブクラスに委譲し、クライアントを具象クラスから分離するパターンです。
219+
- 小さな製品の切り替えや、生成の拡張が見込まれる場合に効果を発揮しますが、クラス数の増加や過剰設計には注意が必要です。
220+
- 実装は言語特性に合わせて設計し、テスト・ドキュメント・影響範囲を必ず確認してください。
221+
222+
出典(一次情報抜粋):
223+
> "オブジェクト指向プログラミングにおいて、ファクトリメソッドパターンは、作成されるオブジェクトの正確なクラスを指定せずにオブジェクトを作成する問題に対処するためにファクトリメソッドを使用する生成パターンである。" — Wikipedia: Factory method pattern
224+
> https://en.wikipedia.org/wiki/Factory_method_pattern
225+
226+
[!CARD](https://en.wikipedia.org/wiki/Factory_method_pattern)
227+
228+
それでは、次回は `Abstract Factory` や `Builder` などの生成パターンの実践的な比較記事を予定しています。
229+
この記事で提示したコードは学習目的に簡潔化しています。実運用に採用する際は要件に合わせて詳細設計・テストを行ってください。
230+
231+
以上、パン君でした!

0 commit comments

Comments
 (0)