ソフトウェア設計

SwiftのAbstract Factoryパターン:関連オブジェクトをまとめて差し替える方法

Abstract Factoryは、互換性のある複数のオブジェクトを製品ファミリーとしてまとめ、一度に差し替えます。Swiftのテーマを例に、組み合わせミスを防ぐ構造とFactory Methodとの選び方を解説します。

読了 5 分
SwiftのAbstract Factoryパターン:関連オブジェクトをまとめて差し替える方法のカバー画像

アプリ画面のテーマをライトからダークへ、まとめて切り替えたことはありますか?

ボタンやラベルの色を一つずつ差し替えていると、どこかを必ず見落とします。ボタンは黒い背景なのに、ラベルだけ白い背景のままになる、といった問題が起こりがちです。

そんなときにぴったりなのがSwiftのAbstract Factoryパターンです。関連するオブジェクトを一つのセットにまとめ、セットごと差し替えます。

一つのオブジェクトの生成箇所を変えるパターンと、製品ファミリー全体を作るパターンでは適用範囲が異なります。まず境界を整理したい方はFactory MethodとAbstract Factoryの違いもご覧ください。

この記事では、Abstract Factoryパターンが何を解決するのか、Swiftコードで関連オブジェクトをまとめて差し替える方法、そして使うべき場面と避けるべき場面を整理します。


Abstract Factoryパターンとは?

一言で答えると、こうです。

互いに調和して使うオブジェクトを一組にして作るファクトリーを、状況に応じて丸ごと差し替えるパターンです。

要点は「一緒に使うべきオブジェクト」です。ダークテーマのボタンとライトテーマの背景が混在すると困りますよね。

Abstract Factoryは、こうした組み合わせミスを防ぎます。

ファクトリーを一つ選べば、そのファクトリーが作る部品同士は自動的に調和します。ライトのファクトリーを選べば、ライトのボタン、ラベル、背景が生成されます。

部品を個別に選ぶのではなく、ファクトリーを丸ごと選ぶのです。

これがAbstract Factoryのすべてです。


Swiftで関連オブジェクトをまとめて差し替える方法

実際のコードで見ると、より明確です。UIテーマを例にします。

まず、作成する部品の仕様(プロトコル)と、それらを生成するファクトリーの仕様を定義します。

protocol Button { func render() -> String }
protocol Label  { func render() -> String }

// ファクトリーは互いに調和する部品セット全体を担当する
protocol ThemeFactory {
    func makeButton() -> Button
    func makeLabel() -> Label
}
まず一つのprotocolを定義するところから始まります
まず一つのprotocolを定義するところから始まります

次に、ライトテーマ用とダークテーマ用のファクトリーをそれぞれ作ります。各ファクトリーは、自分のテーマに合う部品だけを生成します。

ファクトリーを一つ選べば、部品は自動的にセットで付いてくる
ファクトリーを一つ選べば、部品は自動的にセットで付いてくる
struct LightFactory: ThemeFactory {
    func makeButton() -> Button { LightButton() }
    func makeLabel() -> Label  { LightLabel() }
}
struct DarkFactory: ThemeFactory {
    func makeButton() -> Button { DarkButton() }
    func makeLabel() -> Label  { DarkLabel() }
}

画面を描画する側は、ファクトリーを一つ受け取れば終わりです。どのファクトリーかは気にしません。

func buildScreen(with factory: ThemeFactory) {
    let button = factory.makeButton()
    let label  = factory.makeLabel()
    print(button.render(), label.render())
}

// テーマの切り替えはファクトリーの1行を変えるだけ
buildScreen(with: DarkFactory())

LightFactory()DarkFactory()に変えた瞬間、ボタンとラベルが一斉にダークへ切り替わります。

ボタンの色とラベルの色を別々に直す必要はもうありません。

ライトからダークへ、1行変えただけで画面がぴたりと揃いました
ライトからダークへ、1行変えただけで画面がぴたりと揃いました

Factory Methodとは何が違う?

名前が似ていて混同しやすいので、ここで違いを確認しましょう。

区分 Factory Method Abstract Factory
作成対象 1種類のオブジェクト 関連する複数種類のオブジェクト(セット)
焦点 「何を作るか」 「調和するものをまとめる」
代表例 ボタンを一つ生成 ボタン+ラベル+背景を一組で生成

簡単に言えば、Factory Methodは一つの部品を作る方法で、Abstract Factoryはその部品を一組にまとめる方法です。

Abstract Factoryの中でFactory Methodを複数使う、と考えても差し支えありません。


使うべき場面と避けるべき場面

実際に使ってみると、向いている場面と、かえって過剰な場面がはっきり分かれました。

向いている場面

  • テーマ・プラットフォーム・国など、「セット単位」で変わるものが明確なとき
  • iOSとmacOSのように、UI部品群をまとめて差し替える必要があるとき
  • 決済手段やデータベースドライバーを一組ずつ差し替える構造のとき

過剰になりやすい場面

  • 作成するオブジェクトが1〜2種類しかないとき
  • 組み合わせのルールが頻繁に変わり、セット自体が不安定なとき

オブジェクトが一つしかないのにAbstract Factoryを導入すると、コードが増えて読みづらくなります。

セットにまとめる明確な理由があるときに使うのがよいでしょう。


よくある質問2つ

Q. 後から部品の種類を追加するには?

プロトコルにメソッドを追加し、すべてのファクトリーで実装する必要があります。ファクトリーが多いと手間がかかるため、部品の種類が頻繁に増えるプロジェクトでは事前に検討しましょう。

Q. SwiftUIでも使いますか?

もちろん使えます。ただしSwiftUIにはEnvironment@Observableのような独自の注入方法が整っているため、テーマ程度ならそちらのほうが簡潔な場合が多いです。UIKitベース、または純粋なロジック層でセットの差し替えが必要な場合に、Abstract Factoryがより力を発揮します。


Abstract Factoryは結局、「別々に動いてはいけないものを一つの取っ手でまとめる」パターンです。

テーマを1行変えるだけで画面全体がぴたりと揃う体験をすれば、このパターンを使う理由がすぐ実感できます。まずは小さな例から自分で手を動かしてみるのがおすすめです。

あわせて読みたい