ウェブアプリケーションのコードやプロジェクトを作っていくにはいろんなやりかたがあって、 どんなふうに作るか考え抜くのもありだし適当に作るのもありだ。 でも普通は、一般的なパターンに従うほうがいい。そのほうがコードを管理しやすいし、 他の人にもそのコードを理解してもらいやすくなるからである。
最も多用されているデザインパターンのひとつが、ファクトリーパターンだ。このパターンでは、 使いたいオブジェクトを生成するだけのクラスを用意する。ファクトリーパターンの例として、 こんなコードを考えてみよう。
このコードは、ファクトリーパターンを使って Automobile オブジェクトを作る。 こんなふうにするメリットは二つある。 まず、もし後で Automobile クラスに手を入れたり名前を変更したり別のものに入れ替えたりすることになっても簡単にできるということ。 単にファクトリーの中のコードを変更すれば済むわけで、 コードの中で Automobile クラスを使っているところをひとつひとつ修正するとかいうことはしなくてもよい。 二番目のメリットは、仮にオブジェクトの生成が複雑な作業になってしまっても、 そのすべてのファクトリーに閉じ込めてしまえること。 新しいインスタンスを作るたびに毎回同じようなことを繰り返さずに済む。
なにがなんでもファクトリーパターンを使えばいいってわけではない。 この例のコードはとてもシンプルだし、この程度だとファクトリーパターンのおかげで 無駄に複雑になったように見えるかもしれない。 でも、それなりに大規模で込み入ったプロジェクトにかかわる場合は、 変なトラブルに巻き込まれないためにもファクトリーを使っておいたほうがいいだろう。
ウェブアプリケーションを設計するときには、概念的そして構造的に、 特定のクラスのたったひとつのインスタンスにだけアクセスさせるようにしたいということがよくある。 そんなときに使えるのがシングルトンパターンだ。
TODO: NEED NEW SINGLETON CODE EXAMPLE
このコードは、静的 な変数
とgetInstance()
メソッドを使ってシングルトンパターンを実装している。
これらのことに注目しよう。
__construct
が protected 宣言されている。これで、このクラスの外部からは new
演算子で新しいインスタンスを作れなくなる。__clone
が private 宣言されている。これで、clone
演算子でインスタンスをクローンしようとしてもできなくなる。__wakeup
が private 宣言されている。これで、グローバル関数 unserialize()
でのインスタンスのアンシリアライズができなくなる。getInstance()
による 遅延静的束縛 を使う。このメソッドの中ではキーワード static
が使われていて、サンプルのように Singleton
のサブクラスを作れるようになる。シングルトンパターンが有用なのは、たとえばウェブアプリケーションのリクエスト全体で、 たったひとつのインスタンスだけしかないことを保証しないといけない場合だ。 Configurationクラスみたいなグローバルオブジェクトを使っていたり、 イベントキューみたいな共有リソースを使っていたりする場合に活用できる。
ただ、シングルトンを使うときには注意が必要だ。その性質上、シングルトンパターンを使うと アプリケーションにグローバルな状態を導入することになってしまい、テストがしにくくなる。 シングルトンを使いたいという場面では、たいていの場合は依存性の注入が代わりに使える (し、むしろそっちを使うべきだ)。依存性の注入を使えば、不要な結合を アプリケーションの設計から取り除ける。というのも、共有リソースやグローバルリソースを使う オブジェクトが具象クラスについて知らなくてもよくなるからだ。
ストラテジーパターンを使うと、一連のアルゴリズム群をカプセル化して、 クライアントクラス側から特定のアルゴリズムのインスタンスを作れるようになる。 このときに、実際の実装に関する知識はなくてもかまわない。 このパターンにはいくつかのバリエーションがあるけれど、ここでは一番シンプルなものを解説する。
最初に示すのは、アルゴリズム群を表すコード片だ。 シリアライズした配列、JSON、あるいは単なるデータの配列が欲しいとしよう。
このようにアルゴリズム群をカプセル化しておけば、使う側のコードからもうまい具合に使えるようになる。 また、他の開発者が新たな出力形式を追加したとしても、使う側のコードは変更する必要がない。
個々の具象「出力」クラスがOutputInterfaceを実装していることに気づくだろう。 その目的は二つ。まずは、具象実装が従うべきシンプルな規約をあてはめること。 そしてもう一つは、このように共通のインターフェイスを実装することで、 次のセクションで説明する タイプヒンティング が使え、正しい型(この場合は’OutputInterface’)を使っていることを保証できるということだ。
次のコードは、呼び出し側のクライアントクラスが実際に特定のアルゴリズムを使ったり、 必要な振る舞いを実行時に設定したりするものだ。
このクライアントクラスにはprivateなプロパティが用意されている。 実行時には、必ず’OutputInterface’型を設定しておく必要がある。 このプロパティを設定すれば、loadOutput()を呼んだときに、 指定した型の具象クラスのload()メソッドが呼ばれることになる。
フロントコントローラパターンは、ウェブアプリケーションのエントリポイントをひとつだけ (例: index.php) にして そこですべてのリクエストを処理するというパターンだ。このエントリポイントが、 依存情報を読み込んだりリクエストを処理したりレスポンスをブラウザに返したりといった責務を負う。 フロントコントローラを利用すると、コードのモジュール化が進めやすくなる。 また、すべてのリクエストに対して実行したいコード (入力のチェックなど) をフックとして組み込みやすくなる。
モデル=ビュー=コントローラ (MVC) パターン、そしてその関連パターンである HMVC や MVVM を使うと、コードを論理的に分解してそれぞれ特定の役割を担わせることができる。 モデルはデータアクセス層を扱い、データを取得してそれをアプリケーションで使いやすい形式で返す。 コントローラはリクエストを扱い、モデルから受け取ったデータを処理してビューを読み込み、 それをレスポンスとして返す。 ビューはテンプレート (マークアップや xml など) を扱い、これをレスポンスとしてウェブブラウザに返す。
MVC は最も一般的なアーキテクチャパターンで、主要な PHP フレームワーク でも採用されている。
MVC やその関連パターンについてさらに知りたければ、これらを参考にしよう。