Factory Method パターン
基底クラスでファクトリーメソッドを定義し、作成する製品をサブクラスに決定させます。
「Factory Method パターン」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
ファクトリメソッドの目的
ファクトリメソッドは、オブジェクトを生成するためのインターフェースを定義し、どのクラスをインスタンス化するかの判断をサブクラスに委ねます。これにより、生成ロジックとクライアントコードを分離できます。
ファクトリメソッドがない場合の問題
ファクトリがないと、クライアントコードのあちこちに new ConcreteClass() の呼び出しが散在します。新しいバリエーションを追加するたびにすべての呼び出し箇所を変更する必要があり、Open/Closed Principle に違反します。
// Client knows too much:
Shape shape;
if (type.equals("circle")) shape = new Circle(r);
else if (type.equals("rect")) shape = new Rectangle(w, h);
// Every new shape requires editing this code.生成者の抽象クラス
createProduct() ファクトリメソッドを持つ抽象生成者クラスを定義します。サブクラスではこのメソッドをオーバーライドし、具体的なプロダクト型を返します。
public abstract class Dialog {
public void render() {
Button btn = createButton(); // factory method
btn.onClick();
}
protected abstract Button createButton();
}具象生成者
各サブクラスはファクトリメソッドをオーバーライドして適切なプロダクトを返します。これにより、基底クラスの周辺アルゴリズムを変更せずに済みます。
public class WindowsDialog extends Dialog {
@Override
protected Button createButton() { return new WindowsButton(); }
}
public class WebDialog extends Dialog {
@Override
protected Button createButton() { return new HtmlButton(); }
}プロダクトインターフェース
すべての具象プロダクトが共通のインターフェースを実装するため、生成者はそれらを汎用的に扱えます。
public interface Button {
void onClick();
void render();
}
public class WindowsButton implements Button {
public void onClick() { System.out.println("Windows click"); }
public void render() { System.out.println("Render Windows button"); }
}静的ファクトリメソッドとファクトリメソッドパターン
静的ファクトリメソッド(例: LocalDate.of())は命名規則であり、GoF のパターンではありません。GoF のパターンは継承を使いますが、静的ファクトリは1つのクラスに定義した静的メソッドを使います。
// Static factory (NOT the GoF pattern)
LocalDate d = LocalDate.of(2024, 6, 15);
// GoF Factory Method uses a class hierarchyパラメーター付きファクトリメソッド
ファクトリメソッドにパラメーターを渡すことで、プロダクトごとにサブクラスを用意しなくても、複数のプロダクトから選択できます。
public class ShapeFactory {
public static Shape create(String type, double... dims) {
return switch (type) {
case "circle" -> new Circle(dims[0]);
case "rectangle" -> new Rectangle(dims[0], dims[1]);
default -> throw new IllegalArgumentException("Unknown: " + type);
};
}
}ジェネリクスを使ったファクトリメソッド
ジェネリクスを使うと、ファクトリメソッドを型安全にし、異なるプロダクトファミリー間で再利用できます。
public abstract class Repository<T, ID> {
public abstract T findById(ID id);
protected abstract T createEmpty(); // factory method
}Map によるファクトリの登録
レジストリベースのファクトリは、型を表す文字列と Supplier ラムダの対応をマップに保存します。これにより if-else の連鎖を避け、登録を動的に行えます。
Map<String, Supplier<Notification>> registry = new HashMap<>();
registry.put("email", EmailNotification::new);
registry.put("sms", SmsNotification::new);
Notification n = registry.getOrDefault(type, DefaultNotification::new).get();ファクトリメソッドと Abstract Factory の比較
ファクトリメソッドは継承によって1種類のプロダクトを生成します。Abstract Factory はコンポジションによって関連するプロダクトのファミリーを生成します。変化するプロダクトが1つならファクトリメソッドを、スイート全体が一緒に変化するなら Abstract Factory を使います。
実例: Logger ファクトリ
SLF4J の LoggerFactory.getLogger(Class) は、呼び出し側がどの実装かを知らなくても、適切なロガー実装(Logback、Log4j、JUL)を返す静的ファクトリです。
Logger log = LoggerFactory.getLogger(MyService.class);
log.info("Service started");確認問題
ファクトリメソッドパターンの重要な特徴は何ですか。
まとめ
ファクトリメソッドは、インスタンス化の判断をオーバーライド可能なサブクラスのメソッドに置くことで、オブジェクトの生成とクライアントを分離します。クラスが生成する必要のあるオブジェクトを事前に判断できない場合に使用します。
よくある質問
「Factory Method パターン」レッスンは無料ですか?
はい。「Factory Method パターン」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「Factory Method パターン」で何を学びますか?
基底クラスでファクトリーメソッドを定義し、作成する製品をサブクラスに決定させます。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「Factory Method パターン」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Singleton:スレッドセーフな実装
- Factory Method パターン
- 製品ファミリーのための Abstract Factory
- Fluent API を使った Builder パターン