Abstract Factoryパターンとは?Java実装とメリット

Abstract Factoryパターンとは?Java実装とメリット

PR Amazonのアソシエイトとして、ITナレッジライフは適格販売により収入を得ています。

記事の文字数:3,275

関連するオブジェクト群をまとめて生成するためのGoFデザインパターン「Abstract Factory(アブストラクトファクトリー)パターン」について、基本概念からJavaでの実装例、Factory Methodとの違いまで分かりやすく解説します。

ITエンジニアにお勧めの本 ↗

おすすめ

エンジニアが知っておきたい思考の整理術 複雑な情報を【理解する】【伝える】テクニック

難易度
実用性
図解

思考の整理というテーマを、実務ですぐに使える具体的な「技術」として落とし込んだ一冊です。

ベストセラー

世界一流エンジニアの思考法

難易度
実用性
思考法

技術スキル以上に大切な「考え方」をアップデートできる。世界基準の効率的な仕事術が学べます。

文系社会人のためのIT資格の歩き方: 文系のあなたに最適な道をご提案します (YKcreate kiki)

難易度
実用性
キャリア度

ロードマップが非常に明確。キャリアプランを見据えた、無駄のない学習順序を提案してくれます。

エンジニアを説明上手にする本 相手に応じた技術情報や知識の伝え方

難易度
実用性
コミュ力

「伝える技術」もエンジニアの重要なスキル。相手の視点に立った、具体的な説明のコツが満載です。

技術広報入門 ー テックブログから始めるエンジニアカルチャーのつくり方

難易度
実用性
独自性

テックブログを入口にエンジニア組織の文化をどう設計し、育てていくかという実践論が学べます。

UIUI [ユーアイ]User Interface。ユーザーとシステムの間で情報をやり取りする接点や画面のテーマ(ライト/ダーク)を切り替える際、関連するボタンやウィンドウの部品をまとめて差し替えたい」「OSOS [オーエス]Operating System。基本ソフトウェア(Windows/macOSmacOS [マックオーエス]Appleが開発するMac用のオペレーティングシステム)ごとに対応したUIコンポーネントを矛盾なく生成したい」といった課題に直面したことはありませんか?

本記事では、互いに関連するオブジェクト群をまとめて生成するための「Abstract Factory(アブストラクトファクトリー)パターン」について、JavaJava [ジャバ]オブジェクト指向プログラミング言語の実装例を交えてわかりやすく解説します。

記事のポイント

  • Abstract Factoryパターンは、互いに関連・依存するオブジェクト群を、具体的なクラスを指定することなく生成するためのデザインパターンです。
  • 「製品の群(ファミリー)」を一括して切り替えることができるため、設定の矛盾(WindowsのボタンとmacOSのチェックボックスが混ざるなど)を防げます。
  • Factory Methodパターンが「1つの製品の生成」に注目するのに対し、Abstract Factoryパターンは「関連する複数の製品群の生成」に注目します。
  • 新しい製品群(新しいテーマなど)を追加するのは簡単ですが、新しい種類の製品(新しい部品など)を追加するのは難しいという特徴があります。

Abstract Factory(アブストラクトファクトリー)パターンとは?

Abstract Factory(アブストラクトファクトリー) パターンは、GoF(Gang of Four)によって定義された23のデザインパターンのうち、「生成に関するパターン」の1つです。

直訳すると「抽象的な工場」となります。このパターンでは、具体的な実装(どのクラスをインスタンス化するか)をクライアント(利用側)から隠蔽し、インターフェース(抽象クラス)を通してのみオブジェクト群を生成・利用します。

Factory Methodパターンとの違い

どちらもオブジェクト生成をカプセル化するパターンですが、焦点を当てている範囲が異なります。

  • Factory Methodパターン: 主に1種類の製品を生成するためのメソッドを定義し、その具体的な生成方法をサブクラスなどに委ねます。
  • Abstract Factoryパターン: 関連する複数種類の製品を同じファミリーとして生成するためのインターフェースを提供します。Abstract Factoryの各生成メソッドは、Factory Methodとして実装される場合があります。そのため、両者は密接に関連するパターンです。

Abstract Factoryパターンの構造と登場人物

このパターンには、大きく分けて以下の役割を持つクラスが登場します。

  1. AbstractFactory(抽象的な工場) 関連する製品群を生成するためのAPIAPI [エーピーアイ]Application Programming Interface。異なるソフトウェア間の接続口(メソッド群)を定義するインターフェース(または抽象クラス)です。
  2. ConcreteFactory(具体的な工場) AbstractFactory を実装し、特定のバリエーション(テーマやOSなど)に対応する具体的な製品群を生成します。
  3. AbstractProduct(抽象的な製品) 各製品のインターフェース(または抽象クラス)を定義します。
  4. ConcreteProduct(具体的な製品) AbstractProduct を実装した具体的な製品クラスです。
  5. Client(依頼者) AbstractFactoryAbstractProduct のインターフェースのみを使って、具体的なクラスには依存せずに処理を行います。

Abstract FactoryパターンのJava実装例

ここでは、GUIGUI [ジーユーアイ / グーイ]Graphical User Interface。グラフィカルな操作画面アプリケーションにおける「ライトテーマ」と「ダークテーマ」のUIコンポーネント(ボタンとチェックボックス)をまとめて生成する例をJavaで実装します。 ※簡潔にするため複数のクラスをまとめて掲載しています。実際には各publicクラスを対応するファイルに分けてください。

1. AbstractProduct(抽象的な製品)の定義

まずは、生成される各コンポーネント(製品)の共通インターフェースを定義します。

// ボタンのインターフェース
public interface Button {
void paint();
}
// チェックボックスのインターフェース
public interface Checkbox {
void paint();
}

2. ConcreteProduct(具体的な製品)の実装

次に、各テーマ(バリエーション)に対応した具体的なコンポーネントを実装します。

// ライトテーマ用のボタン
public class LightButton implements Button {
@Override
public void paint() {
System.out.println("ライトテーマのボタンを描画します。");
}
}
// ダークテーマ用のボタン
public class DarkButton implements Button {
@Override
public void paint() {
System.out.println("ダークテーマのボタンを描画します。");
}
}
// ライトテーマ用のチェックボックス
public class LightCheckbox implements Checkbox {
@Override
public void paint() {
System.out.println("ライトテーマのチェックボックスを描画します。");
}
}
// ダークテーマ用のチェックボックス
public class DarkCheckbox implements Checkbox {
@Override
public void paint() {
System.out.println("ダークテーマのチェックボックスを描画します。");
}
}

3. AbstractFactory(抽象的な工場)の定義

関連する部品(ここではボタンとチェックボックス)を生成するためのインターフェースを定義します。

// UI部品を生成する抽象ファクトリー
public interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}

4. ConcreteFactory(具体的な工場)の実装

テーマごとに具体的な製品を生成するファクトリーを実装します。

// ライトテーマ用のコンポーネント群を生成するファクトリー
public class LightThemeFactory implements GUIFactory {
@Override
public Button createButton() {
return new LightButton();
}
@Override
public Checkbox createCheckbox() {
return new LightCheckbox();
}
}
// ダークテーマ用のコンポーネント群を生成するファクトリー
public class DarkThemeFactory implements GUIFactory {
@Override
public Button createButton() {
return new DarkButton();
}
@Override
public Checkbox createCheckbox() {
return new DarkCheckbox();
}
}

5. Client(依頼者)クラスと実行例

クライアント側は、渡されたファクトリーの種類を気にすることなく、インターフェース経由で一貫性のある製品群を利用できます。

public class Application {
private Button button;
private Checkbox checkbox;
// コンストラクタでファクトリーを受け取り、必要な部品を生成
public Application(GUIFactory factory) {
button = factory.createButton();
checkbox = factory.createCheckbox();
}
public void paintUI() {
button.paint();
checkbox.paint();
}
}
public class Main {
public static void main(String[] args) {
// 設定や環境に応じてファクトリーを切り替える
String theme = "dark"; // 例えば設定ファイルなどから読み込む
GUIFactory factory;
if (theme.equals("dark")) {
factory = new DarkThemeFactory();
} else {
factory = new LightThemeFactory();
}
// クライアント側は具体的なクラスに依存せずUIを描画できる
Application app = new Application(factory);
app.paintUI();
}
}

実行結果のイメージ:

ダークテーマのボタンを描画します。
ダークテーマのチェックボックスを描画します。

このように、ファクトリーを差し替えるだけで、生成される関連オブジェクトの群(ファミリー)全体を安全に切り替えることができます。ライト用のボタンとダーク用のチェックボックスなど、異なるファミリーの製品が混在するのを防ぎやすくなるのが大きなメリットです。

Abstract Factoryパターンを採用するメリット・デメリット

メリット

  • 製品群の一貫性を保ちやすい:関連するオブジェクトを同じファミリーから生成する仕組みにできるため、異なるファミリーのオブジェクトが混在する不整合を防ぎやすくなります。
  • クライアントと具体的なクラスを疎結合にできる:クライアントは抽象ファクトリーと抽象製品に依存するため、具体的な製品クラスへの依存を減らし、製品ファミリーの切り替えによるクライアント側への影響を抑えられます。これは、具体的な実装への依存を減らし、拡張しやすい設計につながります。
  • 新しいファミリー(製品群)の追加が容易:例えば新しく「マテリアルデザインテーマ」を追加したい場合、新しいConcreteFactoryと関連するConcreteProduct群を追加することで対応しやすく、既存のクライアント処理への影響を抑えながら追加できます。

デメリット・注意点

  • 新しい種類の製品(部品)を追加するのが困難:例えば、後から新しく「テキストボックス」という部品(AbstractProduct)を追加しようとすると、AbstractFactoryインターフェースを変更する必要があり、その影響が全てのConcreteFactoryクラスに及んでしまいます。
  • コードが複雑になりがち:多くのインターフェースとクラスを定義する必要があるため、シンプルなアプリケーションには過剰設計(オーバーエンジニアリング)になる可能性があります。

まとめ:関連するオブジェクト群を一括して切り替えよう

Abstract Factory パターンは、関連する複数のオブジェクト群を、矛盾なく一貫して生成するための強力なデザインパターンです。

「テーマの切り替え」「対応OSごとの部品の切り替え」「データベースの種類(MySQLMySQL [マイエスキューエル]オープンソースのリレーショナルデータベース, PostgreSQLPostgreSQL [ポストグレスキューエル]高機能オープンソースのリレーショナルデータベースなど)ごとの一連のアクセス部品の切り替え※」など、「一連の関連する部品をまとめて差し替えたい」 という要件がある場合に非常に適しています。

※補足:データベースアクセスの切り替えについて、例えばJDBCの DriverManager などは、利用側の文脈によっては Abstract Factory というよりも Factory Method パターンに近い実装となることも多くあります。どちらのパターンに該当するかは、「関連する複数の製品群を作っているか(Abstract Factory)」「単一の製品を作っているか(Factory Method)」によって判断されます。

システムが将来どの方向に拡張されるか(部品のバリエーションが増えるのか、部品の種類そのものが増えるのか)を見極めたうえで、適切に導入を検討してみてください。

【参考情報】


以上で本記事の解説を終わります。
よいITライフを!
ITナレッジライフ 運営者
この記事を書いた人

Z (ITナレッジライフ)

現役のITエンジニア。Linux、プログラミング、IT用語など、日々の業務で得た「痒いところに手が届く」技術情報を発信しています。

プロフィールと編集ポリシーを見る

ITエンジニアにお勧めの本 ↗

おすすめ

エンジニアが知っておきたい思考の整理術 複雑な情報を【理解する】【伝える】テクニック

難易度
実用性
図解

思考の整理というテーマを、実務ですぐに使える具体的な「技術」として落とし込んだ一冊です。

人気記事


記事を評価

Thanks!
目次
Scroll to Top