#02 / 23
C生成DIFF
ファクトリメソッド
Factory Method
『何を作るか』はサブクラスにお任せ。注文を受け付ける本部と、実際に作る各支店の関係。
Intent · 目的
オブジェクトを生成するための『窓口メソッド』だけ親が用意して、中身を作るのはサブクラスに任せる。利用側は「Notification を作って送って」しか言わない ── Email か Slack か LINE かは、現場(サブクラス)が決める。
Motivation · 動機
ある日「通知をメールで送りたい」と書いた `new EmailNotification()`。翌週には Slack も追加。月末には LINE も。気づくと利用側コードのあちこちで `if (channel == ...) new ...()` の分岐が増殖している。生成を抽象メソッド1つに切り出せば、利用側は『誰が作られるか』を知らずに済み、新しい通知方式の追加はクラス1個足すだけで終わる。
適用場面
- 1クライアントは生成対象の具象型を知らなくてよい場合(プラグイン的に種類を増やしたい)。
- 2利用側コードを変えずに、生成する種類だけ差し替えたい場合。
- 3フレームワーク側で骨組みを提供し、利用者には『生成の仕方だけ』を埋めさせたい場合。
概念図
サンプルコード
interface Notification { send(msg: string): void; }
class EmailNotification implements Notification {
send(msg: string) { console.log(`Email: ${msg}`); }
}
class SlackNotification implements Notification {
send(msg: string) { console.log(`Slack: ${msg}`); }
}
abstract class NotificationCreator {
abstract create(): Notification;
notify(msg: string) { this.create().send(msg); }
}
class EmailCreator extends NotificationCreator {
create() { return new EmailNotification(); }
}
class SlackCreator extends NotificationCreator {
create() { return new SlackNotification(); }
}
new SlackCreator().notify("デプロイ完了");Pros · メリット
- +生成と利用が分離され、利用側は具象型の存在すら知らずに済む。
- +『新方式の追加で利用側を触らない』が成立する ── オープン・クローズドの原則の優等生。
- +テスト時にダミーやスタブのファクトリを差し込みやすく、依存の差し替えが楽。
Cons · デメリット
- −Creator のサブクラスがどんどん増え、クラス図が縦に伸びる。
- −種類が爆発するとファクトリも爆発する。『分岐の数』を『クラスの数』に置き換えただけになる罠。
- −1種類しかないのに先回りして導入すると、ただの遠回りなコードになる。
関連パターン
⚔ ready to test
理解度を確かめる時間だ
3 問のクイズで、 このパターンを身体に染み込ませよう。