「それぞれのデザインパターンは、私たちの周りで繰り返し発生する問題と、その解決策の核心を記述している。そうすることで、同じ解決策を何度も何度も、ゼロから考え直すことなく使い回せるようになるんだ」。デザインパターンの核心は、関連する問題への解決策を提供することで、成功した設計やアーキテクチャを簡単に再利用できるようにすることにあるよ。
デザインパターンには、一般的に以下の4つの基本要素があるんだ。
- パターン名 (Pattern Name):パターンの問題、解決策、効果を一言二言で表す名前。
- 問題 (Problem):いつそのパターンを使うべきかを記述したもの。
- 解決策 (Solution):設計を構成する要素、それらの関係性、それぞれの役割や協力方法を記述したもの。
- 効果 (Consequences):パターンを適用した際の結果や、使用する際に考慮すべきトレードオフを記述したもの。
デザインパターンは、含まれるクラスやインスタンス、それらの役割、協力方法、そして責任の割り当てを明確にするんだ。それぞれのデザインパターンは、特定のオブジェクト指向設計の問題やポイントに焦点を当てていて、いつ使うべきか、他の制約下でも使えるか、そして使用した際の効果や取捨選択について説明しているよ。デザインパターンの目的に応じて、大きく3つのカテゴリに分けられるんだ。
生成に関するパターンはオブジェクトの作成に関わり、構造に関するパターンはクラスやオブジェクトの組み合わせを扱い、振る舞いに関するパターンはクラスやオブジェクトの責任分担について記述しているよ。

| 生成に関するパターン | 構造に関するパターン | 振る舞いに関するパターン | |
|---|---|---|---|
| クラス | Factory Method | Adapter (クラス) | Interpreter Template Method |
| オブジェクト | Abstract Factory Builder Prototype Singleton | Adapter (オブジェクト) Bridge Composite Decorator Facade Flyweight Proxy | Chain of Responsibility Command Iterator Mediator Memento Observer State Strategy Visitor |
生成に関するデザインパターン
生成に関するパターンはインスタンス化のプロセスを抽象化するものだよ。これらは、システムがオブジェクトをどのように作成、構成、表現するかから独立するのを助けてくれるんだ。クラスの生成パターンは継承を使ってインスタンス化されるクラスを変え、オブジェクトの生成パターンはインスタンス化を別のオブジェクトに委譲するんだ。
システムがクラス継承よりもオブジェクトの合成に依存するように進化するにつれて、生成に関するパターンはより重要になっていくよ。この状況では、固定された動作をハードコーディングするのではなく、小さな基本動作のセットを定義し、それらを組み合わせて複雑な動作を作ることに重点が置かれるようになる。そうなると、特定の動作を持つオブジェクトを作るには、単にクラスをインスタンス化する以上のことが求められるんだ。
これらのパターンには、繰り返し現れる2つの大きなテーマがあるよ。
- システムがどの具体的なクラスを使用しているかという情報をカプセル化する。
- これらのクラスのインスタンスがどのように作成され、組み合わされるかを隠す。システム全体がこれらのオブジェクトについて知っているのは、抽象クラスで定義されたインターフェースだけになるんだ。
だから、生成に関するパターンは、「何を」「誰が」「いつ」「どのように」作成するかについて、大きな柔軟性を与えてくれるよ。構造や機能が大きく異なる「製品」オブジェクトを使ってシステムを構成できるし、その構成は静的(コンパイル時)でも動的(実行時)でもいいんだ。
構造に関するデザインパターン
構造に関するデザインパターンは、より大きな構造を得るためにクラスやオブジェクトをどう組み合わせるかを扱うよ。構造に関するクラスパターンは、インターフェースや実装を組み合わせるために継承メカニズムを採用する。簡単な例は、多重継承を使って2つ以上のクラスを1つのクラスにまとめ、親クラスのすべての性質を持たせることだね。このパターンは、独立して開発された複数のライブラリを協力させるのに特に役立つよ。その一例がクラス形式の Adapter パターンだ。一般的にアダプターはあるインターフェースを他のインターフェースと適合させ、異なる複数のインターフェースに対して統一された抽象化を提供する。そのために、クラスアダプターは adaptee クラスをプライベート継承し、自らのインターフェースを adaptee のインターフェースで表現するんだ。
構造に関するオブジェクトパターンは、インターフェースや実装を組み合わせるのではなく、オブジェクトを組み合わせて新しい機能を実現する方法を記述する。実行時にオブジェクトの組み合わせを変更できるため、オブジェクトの合成はより柔軟性が高く、静的なクラス合成では不可能な仕組みを実現できるんだ。
振る舞いに関するデザインパターン
振る舞いに関するパターンは、アルゴリズムとオブジェクト間の責任の割り当てに関わっているよ。オブジェクトやクラスのパターンだけでなく、それらの間の通信パターンも記述するんだ。これらのパターンは、実行時に追跡するのが難しい複雑な制御フローを浮き彫りにする。ユーザーの注意を制御フローからオブジェクト間のつながりへと移してくれるんだ。
振る舞いに関するクラスパターンは、継承を使ってクラス間に振る舞いを分配する。その中でも Template Method はシンプルでよく使われるよ。テンプレートメソッドはアルゴリズムの抽象的な定義で、ステップごとにアルゴリズムを定義し、各ステップで抽象操作やプリミティブ操作を呼び出す。サブクラスが抽象操作を定義してアルゴリズムを具体化するんだ。もう一つのクラスパターンは Interpreter で、文法をクラス階層として表現し、それらのインスタンスに対する操作としてインタープリタを実装するものだよ。
振る舞いに関するオブジェクトパターンは、継承ではなくオブジェクトの合成を使う。いくつかのパターンは、対等なオブジェクトのグループが、単独では達成できないタスクをどのように協力して完了するかを記述している。ここで重要なのは、対等なオブジェクトがどうやってお互いを知るかだ。オブジェクト同士が明示的な参照を持ち合うこともできるけど、それでは結合度が上がってしまう。極端な場合、すべてのオブジェクトが他のすべてのオブジェクトを知る必要が出てくる。Mediator は、対等なオブジェクト間にメディエーターオブジェクトを導入することで、この状況を回避し、疎結合に必要な間接性を提供するんだ。