Abstract Factory
バッドプラクティスから学ぶ Abstract Factory による柔軟なシステム設計
柔軟な UI 設計
Abstract Factory パターンは、関連または依存するオブジェクト群を生成するためのインターフェースを提供するデザインパターンです。このパターンを使用することで、具体的なクラスから独立してクライアントコードを構築することができます。これにより、システムの柔軟性と拡張性が向上します。 以下に、Abstract Factory パターンを用いることでエレガントに問題を解決できる例を紹介します。
修正前のコード
まず、修正前のコードを示します。このコードでは、異なる UI 部品(例えば、ボタンとチェックボックス)を作成する際に、具体的なクラスに依存しています。
問題点
このコードにはいくつかの問題があります。
- 高い結合度:
create_ui
メソッドが具体的なクラスに依存しており、新しい OS や UI コンポーネントを追加する際にコードの修正が必要です。 - 拡張性の欠如: 新しい UI スタイルを追加する場合、既存のクライアントコードを修正する必要があります。
修正後のコード
次に、Abstract Factory パターンを適用して問題を解決したコードを示します。
解決された問題
- 低い結合度: クライアントコードは具体的なクラスに依存せず、抽象的なファクトリーに依存するようになりました。これにより、UI コンポーネントの種類を増やす場合でも、クライアントコードを変更する必要がありません。
- 拡張性: 新しい OS や UI スタイルを追加する場合、新しいファクトリークラスを作成するだけで済み、既存のコードに影響を与えません。
このように、Abstract Factory パターンを用いることで、コードの柔軟性と拡張性を高めることができます。
データベース接続の柔軟な管理
もちろん、Abstract Factory パターンの別の例を紹介します。今回は、異なるデータベース接続を抽象化する例を見てみましょう。これにより、アプリケーションは異なるデータベースを簡単に切り替えることができます。
修正前のコード
この例では、アプリケーションが異なるデータベース(例えば、MySQL と PostgreSQL)に接続するためのコードが直接組み込まれています。 このコードにおける問題点を考えてみましょう。
問題点
このコードには以下のような問題点があります。
-
高い結合度:
DatabaseApplication
クラスが具体的なデータベース接続クラス(MySQLConnection
、PostgreSQLConnection
)に直接依存しています。 -
条件分岐による複雑性: 新しいデータベースタイプを追加するたびに、
initialize
メソッド内の条件分岐が複雑になります。 -
オープン・クローズドの原則違反: 新しいデータベースを追加するには既存のコードを修正する必要があり、拡張に対して閉じていません。
-
テストの難しさ: データベース接続のロジックが直接組み込まれているため、テストが難しくなります。
修正後のコード
Abstract Factory パターンを用いて、データベース接続の生成を抽象化します。これにより、新しいデータベースを追加する際に、既存のコードを変更せずに済みます。
解決された問題
-
拡張性の向上: 新しいデータベースを追加したい場合、対応する具体的なファクトリーを追加するだけで済みます。既存のアプリケーションコードには影響を与えません。
-
単一責任の原則: 各ファクトリークラスは特定のデータベース接続を生成する責任を持ちます。これにより、コードの責任が明確化され、メンテナンスが容易になります。
-
コードの柔軟性: アプリケーションコードは具体的なデータベース接続クラスに依存しないため、異なるデータベースを簡単に切り替えることができます。
このように、Abstract Factory パターンを使用することで、異なるデータベース接続の生成を柔軟に管理できるようになります。
通知サービスの柔軟な設計
では、Ruby on Rails を用いて、Abstract Factory パターンによってエレガントに問題を解決する例を紹介します。この例では、異なる通知サービス(例えば、Email と SMS)を扱うシステムを考えます。
修正前のコード
修正前のコードでは、通知の送信がハードコーディングされており、新しい通知サービスを追加するたびに条件分岐を追加する必要があります。
問題点
- 拡張性の欠如: 新しい通知サービスを追加するたびに、
NotificationService
クラスを修正する必要があります。 - 責任の集中: すべての通知ロジックが単一のクラスに集中しており、メンテナンスが困難です。
修正後のコード
Abstract Factory パターンを導入することで、これらの問題を解決します。各通知サービスに対するロジックを独立したファクトリーとして実装します。
解決された問題
- 拡張性の向上: 新しい通知サービスを追加する場合は、新しいファクトリークラスと通知クラスを作成するだけで済み、既存のコードに影響を与えません。
- 責任の分離: 各ファクトリーと通知クラスが独自の責任を持ち、特定の通知サービスに特化したロジックを担当します。
- 可読性の向上: 各通知サービスのロジックが異なるクラスに分かれるため、コードがシンプルで読みやすくなります。
このように、Abstract Factory パターンを使用することで、コードの柔軟性と拡張性を高め、新しい要件への対応を容易にすることができます。