概要

Factory Method がひとつの Product の生成を切り替えるのに対し、Abstract Factory は「関連する複数の Product をまとめて」生成するインターフェースを定義します。たとえば DB 接続先を MySQL と PostgreSQL で切り替えるとき、Connection と Statement を別々のファクトリーで生成すると組み合わせの不整合が起きかねません。Abstract Factory を使えば、ファクトリーを差し替えるだけで関連するオブジェクト群が一貫して切り替わります。この記事では DB アクセス層を題材に Abstract Factory の構造を示し、Factory Method との使い分け基準、Java 17 の record を活用した簡潔な製品クラス定義、Java 21 の sealed interface による型安全な製品分岐を整理します。

使いどころ

開発環境と本番環境で DB(MySQL / PostgreSQL)を切り替え、Connection・Statement を一貫して生成する

UI テーマ(ライト / ダーク)に応じたボタン・テキスト・背景のスタイルセットをまとめて生成する

帳票出力で「和文セット(明朝 + 縦書き + 和暦)」と「英文セット(ゴシック + 横書き + 西暦)」を切り替える

コード例

AbstractFactoryPatternSample.java
public class AbstractFactoryPatternSample {

    // 抽象製品
    interface DbConnection {
        String connect();
    }

    interface DbStatement {
        String executeQuery(String sql);
    }

    // 抽象ファクトリー
    interface DbFactory {
        DbConnection createConnection();
        DbStatement createStatement();
    }

    // 具象製品(Java 17: record で簡潔に定義)
    record MySqlConnection() implements DbConnection {
        @Override
        public String connect() {
            return "MySQL に接続(jdbc:mysql://localhost:3306/mydb)";
        }
    }

    record MySqlStatement() implements DbStatement {
        @Override
        public String executeQuery(String sql) {
            return "MySQL で実行: " + sql;
        }
    }

    record PostgreSqlConnection() implements DbConnection {
        @Override
        public String connect() {
            return "PostgreSQL に接続(jdbc:postgresql://localhost:5432/mydb)";
        }
    }

    record PostgreSqlStatement() implements DbStatement {
        @Override
        public String executeQuery(String sql) {
            return "PostgreSQL で実行: " + sql;
        }
    }

    // 具象ファクトリー
    static class MySqlFactory implements DbFactory {
        @Override
        public DbConnection createConnection() { return new MySqlConnection(); }
        @Override
        public DbStatement createStatement() { return new MySqlStatement(); }
    }

    static class PostgreSqlFactory implements DbFactory {
        @Override
        public DbConnection createConnection() { return new PostgreSqlConnection(); }
        @Override
        public DbStatement createStatement() { return new PostgreSqlStatement(); }
    }

    // クライアント: ファクトリーだけに依存
    static void runDbOperation(DbFactory factory) {
        var conn = factory.createConnection();
        var stmt = factory.createStatement();
        System.out.println(conn.connect());
        System.out.println(stmt.executeQuery("SELECT * FROM users"));
    }

    public static void main(String[] args) {
        System.out.println("=== MySQL ===");
        runDbOperation(new MySqlFactory());

        System.out.println("\n=== PostgreSQL ===");
        runDbOperation(new PostgreSqlFactory());
    }
}

Java 8 / 17 / 21 の完全なサンプルコードは GitHub リポジトリ で確認できます。

Version Coverage

record で具象製品を定義すると、コンストラクタ・getter・equals・toString が自動生成される。var との併用でクライアントコードも簡潔。

Java 17
// Java 17: record で製品を簡潔に定義
record MySqlConnection() implements DbConnection {
    @Override
    public String connect() {
        return "MySQL に接続";
    }
}
// var で型推論
var conn = factory.createConnection();

Library Comparison

標準 API(interface + record)製品ファミリの種類が固定的で、切り替えロジックを自前で管理するとき。具象ファクトリーの数が製品ファミリに比例して増える。
Spring Profiles環境ごとの Bean 定義を Spring の Profile 機能で切り替えるとき。Spring 依存が前提。ライブラリ層では使えない。
SPI(ServiceLoader)JAR 単位でファクトリー実装を差し替え、プラグイン構成にしたいとき。設定ファイル(META-INF/services)の管理が必要。小規模なら過剰設計になりやすい。

注意点

新しい Product の種類を追加すると、すべての具象ファクトリーにメソッドを追加する必要がある。Product の種類が頻繁に変わる場合は設計の見直しを検討する

Factory Method で十分な場面に Abstract Factory を適用すると、インターフェースとクラスの数が不要に増える。関連する Product が2つ以上あるかどうかが判断基準

具象ファクトリーの選択ロジック自体を Factory Method や設定ファイルで切り替えるケースが多い。ファクトリーの生成方法も設計に含めること

FAQ

Abstract Factory と Factory Method はどちらを先に学ぶべきですか。

Factory Method が基本です。1種類の Product の生成委譲を理解してから、複数 Product をまとめる Abstract Factory に進むとスムーズです。

Abstract Factory の具象ファクトリーはどう切り替えますか。

設定ファイルや環境変数で具象ファクトリーのクラス名を指定し、リフレクションやマップで切り替えるのが一般的です。DI コンテナを使うプロジェクトではプロファイルで管理します。

Product を1つしか持たないのに Abstract Factory を使ってもよいですか。

Product が1つなら Factory Method で十分です。Abstract Factory は関連する複数の Product を一貫して生成する必要がある場合に使います。

関連書籍

この記事のテーマをさらに深く学びたい方へ。

※ Amazon アソシエイトリンクを含みます