PHPはてなからはてブロに移動しましたこの広告は、90日以上更新していないブログに表示しています。PHP?(www.doyouphp.jp)で公開していたコンテンツを移行/加筆/修正したものです。公開の経緯はこちらをどうぞ。サンプルコードを手直ししたものをgithubに上げてありますのでそちらもどうぞ。Factoryパターンについて説明します。factory」を直訳すると「抽象的な工場」となりますね。Methodパターンがあります。Methodパターンは製品であるオブジェクトを作る「工場」を用意するパターンです。Factoryパターンも同様にオブジェクトを生成するパターンの1つで、関連し合うオブジェクトの集まり、つまり部品の集まりを生成します。ここで、「抽象的な」というところがポイントです。この工場は「抽象的」な工場で、生成される部品も「抽象的」な部品になります。オブジェクト指向プログラミングでは、「物を抽象化する」ということが重要なポイントとなります。具体的な物を直接扱うのではなく、「具体的な物を抽象化した物」を扱うということです。Factoryパターンは、具体的なクラスを明確にすることなく、関連し合うオブジェクトの集まりを生成するパターンです。データベースを使ったアプリケーションを構築する場合を考えてみましょう。近年の開発・設計方法論では、データベースに関する処理内容とそれ以外のアプリケーション固有の処理(ビジネスロジック)とを分けて設計・実装することが主流になっています。接続やデータの取得、トランザクションなどデータベースだけに関する処理は、本来ビジネスロジックとは関係がないためです。Object)パターンと呼ばれます。DAOパターンを適用する場合、通常エンティティ(データベースの表)の単位でクラスを作成します。データベースを使ったアプリケーションには、当然ですが何らかのデータベースが必要になります。プログラムを作成できても肝心のデータベースがないと動作しない、ひいてはテストできないといった状況になりがちです。場合によってはデータベースが用意できないまま先行して開発を行わなければならないこともあります。このような場合、データベースアクセスをすると見せかける擬似的なオブジェクト(モックオブジェクト)を使うと非常に有効です。このオブジェクトは「アクセスしているように見せかける」だけで、実際にはデータベースにアクセスしません。データベースがなくても、ビジネスロジック側を作成したりテストできます。モックオブジェクトを使って開発した場合でも、最終的には実際にデータベースにアクセスするクラスに切り替える必要があります。これはかなり大変な作業になります。ここでビジネスロジックを記述したコードを書き換えてしまっては再度テストをおこなわなければなりません。これでは何のためにモックオブジェクトを用意したのか分からなくなってしまいます。Factoryパターンが活躍します。Factoryパターンはオブジェクトの生成に注目したパターンで、関連するオブジェクトをその具体的なクラスを意識させないで生成することを目的としています。Factoryパターンの目的は次のように定義されています。互いに関連したり依存し合うオブジェクト群を、その具象クラスを明確にせずに生成するためのインターフェースを提供する。Factoryパターンでは、部品の役割を持つクラスとその部品を作る工場の役割を持つクラスが存在します。その工場には関連し合う部品を生成するためのメソッドがそれぞれ用意されます。関連し合う部品群の種類に応じて、その工場自身も「工場を生成するための工場」によって生成されます。これにより、状況に応じて生成される具体的な部品群を切り替えることができます。Factoryパターンでは工場から生成される部品は抽象化されており、部品の具体的な内容や生成手順をクライアントが意識しなくて済むようになります。Factoryパターンのクラス図と構成要素は、次のようになります。AbstractFactoryクラス部品であるAbstractProductクラスを生成するためのAPIを定義するクラスです。生成するのがConcreteProductクラスではなくAbstractProductクラスとして定義されているところがポイントです。ConcreteFactoryクラスAbstractFactoryクラスのサブクラスで、定義された生成メソッドを実装するクラスです。ここには、具体的な部品であるConcreteProductクラスを返すよう実装されます。AbstractProductクラス部品ごとのAPIを定義するクラスです。ConcreteProductクラスAbstractProductクラスのサブクラスで、ConcreteFactoryクラスから返される具体的な部品クラスです。ClientクラスAbstractFactoryクラスとAbstractProductクラスのAPIのみを利用してプログラミングをおこないます。Factoryパターンのメリットとしては、以下のものが挙げられます。具体的なクラスをクライアントから隠蔽するクライアントは具体的な工場や部品に直接アクセスするのではなく、抽象化された工場や部品のAPIのみを使って部品オブジェクトを生成したりアクセスしたりできます。このため、クライアントを変更することなく、具体的な工場や部品を変更することが可能です。利用する部品群の整合性を保つ関連し合うオブジェクトを扱う場合、その整合性を保つことが重要になります。Factoryパターンを適用することで、オブジェクト群の整合性を容易に保つことができます。部品群の単位で切り替えができるConcreteFactoryクラスは関連する部品の集まりを生成します。ConcreteFactoryクラスを切り替えることで、関連する部品の集まりを容易に切り替えることができます。Factoryパターンの適用例を見てみましょう。ここでは、商品情報と注文情報を取得するアプリケーションを示しています。Factoryパターンを適用し、実データを扱う部品群とダミーデータを扱う部品群を一度に切り替えられるようにしています。先ほどのDAOパターンを適用して、データの取得部分を隠蔽しています。AbstractFactoryクラスに相当するクラスから見ていきましょう。DaoFactoryインターフェースは、2つの部品を生成するためのAPIが定義されています。createItemDaoメソッドとcreateOrderDaoメソッドです。難しいところはありませんね。createOrderDao();}次は、DaoFactoryインターフェースを実装したクラスです。それぞれのcreateItemDaoメソッドとcreateOrderDaoメソッドに注目してください。DbFactoryクラスは実データ、MockFactoryクラスはダミーデータをそれぞれ扱うDAOオブジェクトを生成していることが分かります。}}続いて、DAOに関連するクラス群を見ていきましょう。ItemDaoインターフェースは商品情報、OrderDaoインターフェースは注文情報をそれぞれ取得するためのAPIを定義しています。これらのインターフェースは、AbstractProductクラスに相当します。このサンプルアプリケーションでは、findByIdメソッドにIDを渡すことで情報を取り出せるようにしています。findById($order_id);}次はConcreteProductクラスに相当するクラスです。先のAbstractFactoryクラスとConcreteFactoryクラスの関係と同様に、実データを扱うクラスとダミーデータを扱うクラスに分かれています。実データを扱うクラスはDbItemDaoクラスとDbOrderDaoクラスです。このサンプルアプリケーションでは、商品情報と注文情報をテキストファイルに保存してあり、DbItemDaoクラスとDbOrderDaoクラスがインスタンス化されるときに読み込まれ、商品・注文の各オブジェクトが生成されるようになっています。データファイルと商品クラス、注文クラスについては、後ほど説明します。}}一方のダミーデータを扱うクラスは、MockItemDaoクラスとMockOrderDaoクラスとなります。これらのクラスは、決まった商品データと注文データを返します。}}次に、商品クラスと注文クラスを説明します。これらのクラスは、純粋に商品の情報や注文の情報を内部に保持するだけの役割を担っています。商品を表すItemクラスは、コンストラクタに商品情報(商品IDと商品名)を受け取り、その値にアクセスするためのメソッドが用意されているだけの単純なクラスです。}}注文を表すOrderクラスは、コンストラクタで注文IDを受け取り、注文情報に含まれる商品情報はaddItemメソッドを通じて追加します。注文IDや含まれている商品情報へアクセスするためのメソッドも用意されています。}}ここで、実データについて見ておきましょう。商品情報と注文情報は、固定長データとして用意しました。フォーマットはデータファイル内の先頭行にもありますが、詳細は表を参照してください。複数の場合、商品IDをカンマ区切りで繋げるようやく最後のクライアント側コードの説明です。注目していただきたいのが、このコードには具体的な部品クラス、つまりConcreteProductクラスに相当するクラスが一切出てきていないということです。唯一登場しているのがConcreteFactoryクラスに相当するDbFactoryクラスとMockFactoryクラスです。ConcreteFactoryクラスを切り替えるだけで、部品群を綺麗に切り替えることができています。'の注文情報は次の通りです。Factoryパターンを適用したアプリケーションのクラス図は次のようになっていますので確認してみてください。Factoryパターンを適用したサンプルの実行結果は、次のようになります。Factoryパターンは「ポリモーフィズム」を活用したパターンです。具体的な部品クラスであるConcreteProductクラスは、それぞれの部品ごとに共通のAPIを持っています。これは親クラスであるAbstractProductクラスで定義されています。クライアント側はAbstractProductクラスのAPIだけを使ってプログラミングすることで、具体的なConcreteProductクラスに依存しないコードになります。このことは、部品工場であるAbstractProductクラスとConcreteFactoryクラスにも言えます。この2つのクラスには親子関係がありますが、親クラスであるAbstractFactoryクラスで提供されるAPIだけを使うことで、どのConcreteFactoryクラスなのかを意識する必要がなくなり、具体的なConcreteFactoryクラスに依存しないコードになります。工場から生成される部品はAbstractProductクラスとして生成されますので、ここでも、どのConcreteProductクラスなのかを意識する必要がありません。このため、どのConcreteFactoryクラスを使うかを切り替えるだけで、芋づるのように生成されるConcreteProductクラス群を切り替えることができます。オブジェクト指向プログラミングでは、具体的なクラスではなくインターフェースや抽象化されたクラスのAPIに対してプログラミングすることが重要になります。Methodパターンを使って実装される場合が多いですが、Prototypeパターンを適用して実装することも可能です。SingletonパターンConcreteFactoryクラスにSingletonパターンが適用される場合が多くあります。Factoryパターンについて見てきました。12はてなブログをはじめよう!shimookaさんは、はてなブログを使っています。ブログを報告する引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。