デザインパターン再入門

はじめに

前回に続いて、「JavaWorld(2005/8)」を参考に、
デザインパターンの入門的な内容を解説します。
 

デザパタとは?

デザパタとは、
オブジェクト指向における「定石」や「決まりきったやり方」
のことを言います。
 
と、いうとなんだか、
数学の公式みたいに「暗記」しなければならないもの
というイメージが湧いてきませんか?
 
私も最初、そんなイメージがあったので、必死に暗記しようとしました。
 
それで、暗記の甲斐があって、いくつかのパターンを覚えたのですが、
それらは、、、



全く使う機会がありませんでした!!!!!
 
ΩΩΩ<な、なんだって〜〜?!
(ざわざわ…)
 
 
というのはですね。
よく言われることなのですが、
デザパタは、そのままでは実戦で使うことができない」
という事実があります。
 
パターンという言葉が悪いのかもしれません。
 
むしろ、考え方、というほうが適切で、
オブジェクト指向に対する、優れた考え方、という感じでしょうか。
 
つまり、パターンをよく理解せず丸暗記しても、
何の役にも立たない、というわけです。
 
 
あと、もう一つ、デザパタに対する別の見方があります。
 
それは、
オブジェクト指向を正しく理解するためのパターン」
という考え方です。
 
例えば、前回説明した、

  • ユニットクラスを継承して、戦士・魔法使い・僧侶を作る

というのは、実は「テンプレートメソッド」というパターンだったりします。
 
これは、パターンというよりも、
オブジェクト指向で開発するなら、知っていて当たり前ですよね。
 
というように、デザパタを理解することは、
オブジェクト指向を正しく理解することでもあるわけです。
 

デザパタのメリット

デザパタを学ぶメリットはいくつかありますが、だいたいはこんな感じです。

  1. 優れたパターンが再利用できる
  2. オブジェクト指向に対する色々な考え方が身につく
  3. コミュニケーションが円滑になる

1は、まあ、パターンをそのまま使うことはできませんが、
とりあえず「車輪の再発見」は避けられると思います。
 
2は、前段で述べたとおりです。
 
3は、引継ぎなどで設計の説明をする場合に、
「これはObserverパターンを適用しています」
「ああ、なるほど。このメソッドでAttachしてるわけやね」
といった感じで、共通のキーワードで迅速にコミュニケーションを行うことができます。
 
 
この中でも、一番重要なのが2ですね。
色々な考え方が身につくことにより、
「この仕様を満たすには、このパターンに手を加えて、こうすればイケるんじゃない?」
と考えられるようになれば、しめたものです。
 

デザインパターンの領域

デザインパターンが設計において、
どこからどこまでをカバーするのかを知っておくことも重要です。
 
まず、一番大きな領域は、アーキテクチャ・パターンです。
これは、コンポーネントの構成・つながりをパターン化したものです。
MVC」や「レイヤ」、「Doc&View」などがこれに当たります。
ゲームで言えば、デバイスコンポーネントとステージコンポーネント
モデリングコンポーネントなどの「コンポーネント同士の大きなつながり」といった、
コンポーネントの外部的な構成を表したものです。
 
次が、デザイン・パターンです。
ここで、コンポーネントの内部構成が対象となります。
具体的には、DirectGraphicsクラスとDirectX管理クラスとのつながりなど、
クラスレベルでの設計のパターンを表します。
 
最後に、イディオムです。
個々のプログラム言語のパターンですね。
例えば、コーディングパターンです。
 
 
つまり、デザパタは「1つのコンポーネントの作り方」についてのパターンともいえるわけです。
 

デザパタの読み方

デザパタには、バイブルと言われる(GoF本)があります。

オブジェクト指向における再利用のためのデザインパターン

オブジェクト指向における再利用のためのデザインパターン

こいつです。
しかし、これはちょっと難しいです。
 
そこでオススメしたいのがこちらです。
増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門

 
この本は難解なGoF本を、とても丁寧に、分かりやすく解説しています。
GoF本で挫折したなら、間違いなく買って損はないですね。
(むしろ私にとっては、こっちがバイブルだったりしますw)
 
どちらにしても、デザパタは以下の読み方をオススメします。

  1. パターンの目的と動機を理解する
  2. とりあえず、動かしてみる(そしてデバッカで追いかけてみる)
  3. そして、驚いてみる
  4. ゲームで使えないかと考えてみる
  5. 関連するパターンをチェックする

 
1は、それぞれのパターンは「なんらかの問題を解決する」ために存在します。
パターンを理解するには、どういった問題を、どのように解決するのか、
といった背景を含めて理解する必要があります。
例えば、テンプレートメソッドの目的について言うと、以下のようになります。
(テンプレートメソッドの具体例は
http://www5f.biglobe.ne.jp/~kenmo/program/design2/design2.html#2
を参考にしてください)

アルゴリズムの各ステップの実行順を基底クラスで定義し、
サブクラスで各ステップを実装する。
つまり、各ステップの実行順を変更することなしに、
特定のステップを変更することができる。

このパターンで重要なのが、

  • 各ステップの実行順は変更できない
  • 各ステップの処理の中身は変更できる

ということです。
 
ここでもう一度、「開放−閉鎖原則」を思い出します。

モジュールは、
「拡張」に対して開いており、
「修正」に対して閉じていなければならない。

オブジェクト指向の目的は、「拡張」を容易にすることです。
つまり、機能要件(問題)として、

  • 各ステップの処理の中身は変更できる

ということが存在することが必要です。
 
そして、その解決策として、
基底クラスで「各ステップの実行順を定義」しているのが、
テンプレートメソッドの背景にあるものとなります。
 
2の動かしてみる、ということも重要ですね。
http://www.hyuki.com/dp/index.html
サンプルソースがあるので、
Java+Eclipseで、デバック実行で動きを確認するのもいいですね。
 
そして、
「Oh!こんな動きをするんだ!」
と派手に驚いてみるのもいいです。
 
また、そのソースを別の言語に移植したり、ゲームに使えないかな、
などと考えてみるのもいい勉強になります。
 
で、何気に重要なのが、
5の「関連するパターンをチェックする」です。
 
実はテンプレートメソッドには、類似するパターンがいくつかあります。
「状態」の変化により、アルゴリズムを入れ替える、ステートパターン。
「戦略」の切り替えのためにアルゴリズムをごっそり入れ替える、ストラテジーパターン。
アルゴリズムの定義でなく、「インスタンスの生成」の定義を目的としたテンプレートメソッドである、ファクトリーメソッドパターン。
です。
 
このように、何か1つのパターンを理解したら、「類似したパターン」をチェックすることが大切です。
こうすることにより、学習効果は爆発的に上がります。
(補足:類似するパターンがあるということは、間違えて目的に合致しないパターンを選択してしまうことがあります。
 最悪の場合、その部分はメンテナンス不可、という状態になってしまうことがあります。
 そうならないように、目的(機能要件)に沿ったパターンを吟味することが大切、とも言えます)
 
また、パターンは「組み合わせる」ことにより威力が発揮するものもあります。
例えば、
http://www5f.biglobe.ne.jp/~kenmo/program/design3/design3.html
のように、インタプリタパターンとビジターパターンは、
組み合わせることにより、効率的に処理を行うことができます。
 
 

最後に

デザパタは全部で23種類もあるので、勉強するのが大変です。
 
ですが、中には
「これは、あまり使わないんじゃないの〜」
というものがあります。
 
ということで、個人的に頻出と思われる、以下の2つをまず理解することをオススメします。

  • テンプレートメソッド
  • ファクトリーメソッド

 
この2つは、オブジェクト指向で開発するのであれば、必須です。
(というか、これを使わない場合は、なんのためにオブジェクト指向を使うのか…w)
 
そして、この2つが理解できたら、
参考ページの「デザインパターンを読み解く」の
「上位コンセプト(クラス構成の方法であってテクニックではない。自然に使うもの)」
というパターンを重点的に理解するのがいいと思います。

  • Factory Method
  • Abstract Factory
  • Builder
  • Proxy
  • Facade
  • Memento
  • Prototype
  • Template
  • Mediator
  • Observer
  • Bridge

こいつらですね。
 
以上です♪