PHPはてなからはてブロに移動しましたこの広告は、90日以上更新していないブログに表示しています。PHP?(www.doyouphp.jp)で公開していたコンテンツを移行/加筆/修正したものです。公開の経緯はこちらをどうぞ。サンプルコードを手直ししたものをgithubに上げてありますのでそちらもどうぞ。生成+オブジェクトはじめにここではBuilderパターンについて見ていきましょう。「builder」とは、「建築者」や「建設業者」の意味を持つ単語ですが、たとえば、家を建てることを考えてみましょう。最終的に建てられる家は、「どの様な順序で、どこに何を配置していくか」という「手順」と、「柱や壁、屋根に何を使うか」という「材料」によって大きく違ってきます。Builderパターンは、この「手順」と「材料」を分けておき、同じ手順で異なるオブジェクトを生成させるパターンです。ある条件によって作成するオブジェクトを変更するといった場合を考えてみましょう。普通に考えると、if文やswitch文で処理を分岐し、生成するオブジェクトを切り替えるだけで済んでしまいそうですね。オブジェクトを生成するのに複雑な手順が必要だった場合はどうでしょうか?大量のif文やswitch文で処理を分岐してやる必要がありそうですね。いった場合、「何を作るのか」に依存しないように具体的な生成手順をまとめておけると、簡単に色々なオブジェクトを生成できそうです。ひとつ、あるフォーマットに従ったデータを読み込んで、そのデータを格納するクラスを考えてみましょう。この場合、データの解析処理はどこに記述すると良いでしょうか?たとえば、このクラスの中でデータを処理させるとしましょう。この場合、データを渡すだけでクラスのインスタンスが生成でき、またデータの処理もクラスの内部に閉じこめることができます。データの処理が非常に複雑な場合はどうでしょうか?このクラスのコードの大部分は、その処理に関するコードになってしまうでしょう。このクラスの本来の目的は、データを格納することのはずですが、データの解析処理も含めると非常に分かりにくいコードになってしまいます。データを保持するクラスにはできるだけその目的に専念させ、データの処理部分は他のクラスに任せたいものです。すればクラスの「責任」がはっきりし、クラスの構造がシンプルになりますので、コードも分かりやすいものになるはずです。クラスの再利用性も高まると予想されます。このように、オブジェクトを「何を生成するか」と「どのように生成するか」を分離するパターンがBuilderパターンです。Builderパターンとは?Builderパターンは、オブジェクトの生成に注目したパターンで、オブジェクトの「生成手順」と「生成手段」を分離することを目的としています。GoF本では、Builderパターンの目的は次のように定義されています。複合オブジェクトについて、その作成過程を表現形式に依存しないものにすることにより、同じ作成過程で異なる表現形式のオブジェクトを生成できるようにするBuilderパターンでは、まずクライアントがどのようなオブジェクトを生成するかを選択します。「材料」を選択するということです。この材料は、最終的に生成されるオブジェクトの生成処理を知っています。この材料を「建築者」に渡すことで、実際のオブジェクトの生成をお願いします。一方の「建築者」ですが、渡された材料からどの様なものができるのか知りません。自らが知っている手順に沿って、オブジェクトの生成をおこなうだけです。1つのクラスに生成手順と生成手段をすべてまとめた場合、クラスが複雑になりすぎる傾向があります。ここでBuilderパターンを適用して生成手順を分離することで、構造がシンプルになり、再利用性も高まります。Builderパターンの構造Builderパターンのクラス図と構成要素は、次のとおりです。Builderクラスオブジェクトの「生成手段」を提供するクラス群で最上位に位置するクラスです。オブジェクトを生成するためのAPIを定義します。ConcreteBuilderクラスBuilderクラスで提供されるAPIを実装するサブクラスです。生成したオブジェクトを取得するためのメソッドを提供します。Directorクラス「建築者」に相当するクラスで、Builderクラスで定義されたAPIを使ってオブジェクトを生成します。Productクラス最終的に生成されるオブジェクトのクラスです。BuilderパターンのメリットBuilderパターンのメリットとしては、以下のものが挙げられます。Productオブジェクトの生成過程や生成手段を隠すことができるBuilderクラスでは、Directorクラスにオブジェクトを生成するためのAPIを提供しています。Directorクラスでは、このAPIを使ってのみProductオブジェクトを生成します。DirectorクラスはProductオブジェクトの生成過程やProductオブジェクトの生成手段を知りません。このため、新しいProductオブジェクトを作る必要がある場合、新しいConcreteBuilderクラスを追加するだけで済みます。オブジェクトの生成過程や生成手段のコードを局所化できるBuilderパターンは、オブジェクトの生成過程と生成手段を分離するパターンです。Directorクラスにはオブジェクト生成過程のコードだけが、ConcreteBuilderクラスにはオブジェクトの生成手段のコードだけが記述されることになります。生成過程と生成手段それぞれに関するプログラムコードを凝縮できるということです。独立して修正・拡張することが可能になります。Builderパターンの適用例Builderパターンの適用例を見てみましょう。これは、ニュース一覧をインターネット経由で取得し、一覧表示するアプリケーションです。1つの記事を格納するNewsクラスから始めましょう。Newsクラスは、記事のタイトル、URL、記事の対象日付を保持するだけのクラスで、これら3要素をコンストラクタで受け取ります。}}続けて、外部のサイトからニュース記事を取得し、Newsオブジェクトの配列を作成するクラスたちです。最終的なNewsオブジェクトの配列を生成するNewsDirectorクラスです。Directorクラスに相当します。コンストラクタの引数に、NewsBuilder型のオブジェクトが指定できるようになっています。実際のNewsオブジェクトの生成は、内部に保持したNewsBuilderオブジェクトを使って生成しています。}}次に、先ほど出てきたNewsBuilderクラスについて説明しましょう。これはインターフェースとして宣言しており、parseメソッドを定義しています。先のNewsDirectorクラスは、このparseメソッドを使ってNewsオブジェクトの配列を取得しています。parse($data);}先ほどのNewsBuilderクラスを実装するクラスが、RssNewsBuilderクラスです。名前からも分かるように、ニュース記事としてRSSからデータを取得します。Summary)は、ウェブログや新聞社、その他企業でも更新情報の配信などに利用されている文章フォーマットです。今回は、PHP5から導入されたSimpleXML拡張機能を利用しています。}}最後にクライアント側のコードです。NewsDirectorクラスのコンストラクタに、RssNewsBuilderオブジェクトとURLを渡していますね。他のフォーマットで記述された記事データからNewsオブジェクトの配列を生成する場合、このRssNewsBuilderオブジェクトを変更するだけで対応可能になります。これは、「何を生成するか」と「どのように生成するか」を切り分けた結果、可能になるものです。);}最後にサンプルコードのクラス図を示しておきます。適用例の実行結果Builderパターンを適用したサンプルの実行結果は、次のようになります。Builderパターンのオブジェクト指向的要素Builderパターンは「ポリモーフィズム」と「委譲」を活用しているパターンです。「建築者」であるDirectorクラスには、「材料」であるBuilder型のオブジェクト、具体的にはConcreteBuilderクラスのインスタンスが渡されます。ここで、渡されたBuilder型のオブジェクトが具体的にどのクラスのインスタンスなのかを知りません。Builderクラスで提供されているメソッドは知っていますし、それらを呼び出すことで目的とするオブジェクトが生成されることも知っています。具体的にどの様なオブジェクトが生成されるかは知りません。ここまで見てきたように、DirectorクラスはBuilderクラスのAPIしか知りません。それらAPIの具体的な処理内容は、BuilderクラスのサブクラスであるConcreteBuilderクラスで実装されています。ConcreteBuilderクラスがどのようなものであれ、BuilderクラスのAPIが実装されているものであれば、Directorクラスは正しく機能するということになります。この「具体的な実装が何かを知らない」ことが、オブジェクト指向プログラミングでは重要になってきます。「知らないからこそ入れ替えが可能」になるのです。DirectorクラスとBuilderクラスの間には、強い結びつきはありません。Builder型のオブジェクトをDirectorクラスの内部に保持することで、ゆるく結びつけられています。Directorクラスの処理内容は、内部に保持したBuilder型のオブジェクトのメソッドを呼び出し、具体的な処理を任せています。この関係を委譲と呼びます。この緩い結びつけのため、Builder型のオブジェクトをプログラムの実行中に変更したりできるのです。Factoryパターンも複雑なオブジェクトを生成するパターンです。Factoryパターンは、それぞれの部品の集まりに注目したパターンです。CompositeパターンBuilderパターンによって生成されるオブジェクトは、Compositeパターンになる場合があります。まとめここでは、「何を生成するか」と「どのように生成するか」を切り分けるBuilderパターンを見てきました。12はてなブログをはじめよう!shimookaさんは、はてなブログを使っています。ブログを報告する引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。