Loading...

【ソフトウェア開発】基本のデザインパターン36種類を簡単に整理する【GoF + Game Programming Patterns】

おすすめ技術書
マイケル
マイケル
みなさんこんにちは!
マイケルです!!
エレキベア
エレキベア
クマ〜〜〜〜
マイケル
マイケル
今日はソフトウェア開発における
デザインパターン について紹介するぜ!
エレキベア
エレキベア
デザインパターンって何クマ?
マイケル
マイケル
簡単に言うとこれまでのソフトウェア開発者がまとめた
設計ノウハウを各パターンとして名前をつけたようなもの
だね。
マイケル
マイケル
よく聞くSingletonやFacadeクラスなんかも
デザインパターンとして含まれているんだ。
エレキベア
エレキベア
それは中々興味深いクマね
マイケル
マイケル
それでは早速見ていこう!
スポンサーリンク

デザインパターンとは

マイケル
マイケル
デザインパターンはさっき言った通り、設計ノウハウをパターンとしてまとめたものだ。
この用語が初めて発表されたのは、GoF(※1)と呼ばれる4人の開発者が23のパターンをまとめた「オブジェクト指向における再利用のためのデザインパターン」という書籍からだ!


※1)Gang of Four、イカした4人組という意味らしい

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

エレキベア
エレキベア
初版が1994年・・・
ということはJava(1995年)が出来るよりも前クマね
マイケル
マイケル
そんな昔に発表されたパターンが現在でもしばしば使われているほど、
汎用性の高い設計パターンになるよ。
フレームワークよりも小さく、テクニックのようなものになるね。

オブジェクト指向設計の原則

マイケル
マイケル
書籍の名前にもある通り、GoFのデザインパターンは
オブジェクト指向言語における設計方法 についてまとめたものになります。
エレキベア
エレキベア
オブジェクト指向は奥が深いクマからね
マイケル
マイケル
そんな オブジェクト指向設計の原則 は下記の2つで、デザインパターンはこの考え方を元に作られたとされているよ。
1. インタフェースに対してプログラミングする
マイケル
マイケル
これは インタフェースを定義し、それを元に実装することで柔軟なコード設計にすることができる ということを示しています。
エレキベア
エレキベア
確かに直接クラスを参照していたら依存関係が強まるばかりクマね
2. クラス継承よりコンポジションを多用する
マイケル
マイケル
これもよく言われている話で、
継承(is-a)よりもコンポジション(has-a)を使用する方が依存関係が少なく柔軟になるとされています。
マイケル
マイケル
ケースバイケースではありますが、同じ性質を持たせたい場合には継承、それ以外はコンポジション 等というように基本的にはコンポジションを使用するようにした方が依存は少なくなります。
エレキベア
エレキベア
中々使い分けが難しいところクマね

学ぶメリット・デメリット

マイケル
マイケル
そんなデザインパターンですが、学ぶメリットとしては下記があると思います。


[メリット]
・最適なコード設計にたどり着きやすい。
・変更に強い柔軟なコードになる。
・共通認識として使用でき、把握しやすい。

エレキベア
エレキベア
「このパターンが使われてるな」といった共通認識があるのはすごくいいクマね
マイケル
マイケル
そして逆にデメリット、注意点としては下記があります。


[デメリット]
・使い過ぎてしまうこと。

マイケル
マイケル
学んだからといって使いすぎてしまうと、
コードが複雑になったり、パターンによっては実行速度が落ちる可能性もあります。
そのため、使用するかどうかの判断は慎重に行い、適切な場面で使用する ことが大事になってきます。
エレキベア
エレキベア
これはなんでもそうクマね
知識や技術を乱用してもいい結果にはならないクマ
マイケル
マイケル
ちなみに僕は「デザインパターンを学ぶべきかどうか?」については、プログラマなら知っておいて損はない と思っています。
そのため、どんなものがあるのかを知っておいて、必要になった時に引き出しとして持っておくというのがいいと思います!
エレキベア
エレキベア
やったるクマ〜〜〜

GoF23パターン

マイケル
マイケル
それでは最初に紹介したGoFのパターンを見ていきましょう!

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

マイケル
マイケル
上記の本が原著になるけど、下記の書籍がJavaで簡潔に書かれていて分かりやすい
という話をよく聞くのでおすすめです。(僕は読んでないですが・・・)

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

マイケル
マイケル
GoFは全部で23パターンあって、

・生成に関するパターン
・構造に関するパターン
・振る舞いに関するパターン

の3つの分類に分かれています!
マイケル
マイケル
各パターンについて一言ずつ簡潔にまとめてみたので、
もし詳細が知りたくなったらパターン名でググってみてくださいね。
エレキベア
エレキベア
(投げたクマ・・・。)
生成に関するパターン
パターン名 内容 使いどころ
Abstract Factory オブジェクトの生成処理を共通化するインタフェースを提供する。 オブジェクトの生成を条件によって分岐したい時。
Builder オブジェクトの生成過程を共通化するインタフェースを提供する。 オブジェクトの初期化を条件によって分岐したい時。
Factory Method オブジェクトの生成と生成過程を継承元のサブクラス内メソッドで行う。(Template Methodパターンを使用。Abstract Factory、Builderパターンよりは抽象度は下がる。) オブジェクトの生成、初期化を条件によって分岐したい時。生成をクラスで分けるほど複雑でない時。
Prototype オブジェクトの原型を作成し、コピーすることで作成する。 オブジェクトを状態含めてクローンしたい時。
Singleton オブジェクトが1つ以上存在しないようにする。 オブジェクトが複数あって欲しくない時。
構造に関するパターン
パターン名 内容 使いどころ
Adapter あるインタフェースをクライアントが求めるインタフェースに変換(拡張)するパターン。 編集できないインタフェースを求める形に変換したい時。
Bridge 実装を拡張するためのクラス階層(Impl)を持たせることでそれらを独立に変更できるようにする。 実装クラスと拡張クラスを自由に組み合わせたい時。継承によってごちゃらせたくない時。
Composite 容器と中身を同一化することで再帰的な構造を作る。 ディレクトリ内にディレクトリとファイルが存在する、階層の中に更に階層があるような時。
Decorator 責任(機能)をDecoratorとして作成し、オブジェクトに動的に追加する。 柔軟に機能を追加、拡張したい時。
Facade 複数のインタフェースに1つの統一インタフェースを与える。複雑さを軽減し、依存関係を小さくすることができる。 複数のクラスの呼び出しをまとめたい時。複雑さを軽減したい時。
Flyweight 同じインスタンスを別々の箇所で使用する場合に、インスタンスを再利用することでコストを抑える。 文字オブジェクト、タイル等、複数種類のオブジェクトが大量にある時。
Proxy オブジェクトへのアクセスの代理、入れ物を提供する。間に挟むことで、オブジェクトへのアクセスが間接的になる。 オブジェクトの中間的な処理を置きたい時。
振る舞いに関するパターン
パターン名 内容 使いどころ
Chain of Responsibility 要求を受信するオブジェクトを鎖状に繋ぎ、処理が可能なオブジェクトに渡るまで次のオブジェクトに渡していく。 受信側のオブジェクトを柔軟に追加、変更したい時。結びつきを緩くしたい時。
Command 要求をオブジェクトとしてカプセル化することでコマンドの実行、取り消しを可能にする。 コマンド実行をオブジェクトとして切り離したい時。実行したコマンドを管理し、取り消し/再実行を行いたい時。
Interpreter 各クラスで構文解析の規則を表現し、解析結果を受け渡す。正規表現やSQL等で使用されている。 構文解析を行いたい時。
Iterator 集約オブジェクトの内部表現を公開せずに、要素に順にアクセスする方法を提供する。 List等の内部表現を公開せずに順にアクセスしたい時。複数の走査オブジェクトに共通のインタフェースを提供したい時。
Mediator オブジェクト間の相互通信を仲介する。Facadeが一方通行であるのに対し、Mediatorは双方向に通信を行う。 オブジェクト間の通信を仲介させたい時。
Memento オブジェクトの状態を外部に記録し、保存/復元を行う。 状態の保存、取り消し/再実行を行いたい時。
Observer オブジェクトの状態が変更された時、自動的に知らされるよう一対多の依存関係を定義する。 状態が変更されたことを複数のオブジェクトに通知したい時。
State 各状態の振る舞いを表すオブジェクトを導入し、呼び出し側では状態遷移を定義する。 オブジェクトの複数の状態を明確に分けたい時。
Strategy 複数のロジックのインタフェースを変数として用意することで戦略的にロジックを切り替えるパターン。(コンポジション) アルゴリズム的な処理を入れ替えたい時。(ソート、テキスト処理等)
Template Method 大まかな処理を基底クラスに定義し、具体的な処理はサブクラスに任せる。(継承) 一連の処理の流れが決まっているが、様々なパターンがある時。
Visitor データ構造と処理を分離する。訪問者クラスを用意し、データ構造の中を渡り歩いて処理を行う。 オブジェクトに対するオペレーションを分離して柔軟性を持たせたい時。
マイケル
マイケル
以上23パターンになります!
聞いたことがある名前も多かったのではないでしょうか?
ざっくりした説明を見た上で実際に各パターンのコードを見てみるのが一番分かりやすいと思うので、是非ここから調べてみてください!
エレキベア
エレキベア
これまで無意識に実装していたのもこのパターンだったのか、
みたいなのも結構あって面白いクマね

ゲームプログラミング13パターン

マイケル
マイケル
そしてこれに加えてゲームプログラミングでよく使用するパターンとしてまとめられている有名な書籍もあるため紹介します!
それがこちら、「Game Programming Patterns」です!

Game Programming Patterns ソフトウェア開発の問題解決メニュー impress top gearシリーズ

エレキベア
エレキベア
これはゲームプログラマ必見クマね
マイケル
マイケル
この内容はWebでも公開されているので、是非チェックしておこう!
(英語だけど)

Game Programming Patterns

マイケル
マイケル
内容としては、Commandパターン、ObserverパターンといったGoFの中でよく使用するパターンに加えて、ゲームプログラミングでよく使用する13パターンについて記載されています。
マイケル
マイケル
分類としては、

・シーケンスのパターン
・ビヘイビアのパターン
・分離のパターン
・最適化のパターン

の4種類に分けられています。
シーケンスのパターン
パターン名 内容 使いどころ
Double Buffer 現在の状態、次の状態を持たせておき、切替を一瞬で行ったように見せる 描画処理等、情報を瞬時に切り替えたい時。
Game Loop 入力に関わらず常にループを実行する。FPSを調整して間隔を調整する。 入力に関わらず一定時間でループを実行したい時。
Update Method 個々のオブジェクトに更新メソッドを持たせ、メイン処理から呼び出す。 同時に多数のオブジェクトのループ処理を行いたい時。
ビヘイビアのパターン
パターン名 内容 使いどころ
Byte Code ビヘイビアを命令として持たし、独自の仮想マシンコードで実行する。 プログラムの信頼性が最重要となり、使用している言語やツールに問題がある場合。
Subclass Sandbox 継承によって共通処理を基底クラスにまとめる。Template Methodパターンとは逆に、処理の流れは各サブクラスが定義する。 大まかな振る舞いはサブクラスが決めたい時。外部サービスへのアクセスを基底クラスにまとめたい時。
Type Object 基底クラスに系統を表すクラス(Breed)を持たせて、オブジェクトごとに異なるデータを設定する。また、parentを持たせて親子階層も定義する。 1クラスで複数系統のクラスを生成したい時。
分離のパターン
パターン名 内容 使いどころ
Component 物理シミュレーション、グラフィックス等、ドメインごとにコンポーネントとして分割し、処理を委譲する。 利用しているドメインを分離しておきたい時。継承では再利用したい部品がうまく組み合わせられない時。
Event Queue 受け取ったイベント(メッセージ)をキューとしてグローバルに管理し、実行する。Observerの非同期版。 イベント(メッセージ)を非同期に実行管理したい時。
Service Locator SingletonなServiceとして一箇所に登録し、呼び出せるようにする。
呼び出し側は基底クラスを指定することで差し替えも可能になる。
Singletonを柔軟に管理したい時。呼び出し元をまとめたい時。
最適化のパターン
パターン名 内容 使いどころ
Data Locality ポインタが飛び回らないように、またキャッシュミスを減らすよう意識して実装する。例えば同じクラスのデータは配列にまとめて処理する。 柔軟性より高速化を求める時。キャッシュを効率よく使いたい時。
Dirty Flag 古くなっていることを示すダーティ(汚い)フラグを用意し、必要な時のみ処理を行うようにする。 位置情報更新処理など、都度計算すると重くなる時。
Object Pool オブジェクトの破棄を行わず、プールクラス内で使用状態を管理して使い回す オブジェクト生成が何度も必要な時。生成によるメモリ断片化を防ぎたい時。
Spatial Partition 空間を分割し、特定セル内のオブジェクトに対してのみ処理を行うことで効率化する。 オブジェクトが広い範囲に散見している場合に効率よく判定を行いたい時。
マイケル
マイケル
ゲーム開発で必ず通るような基本的なパターンから、
最適化のパターンまで幅広くまとめられているので詳細も是非調べてみてください!
エレキベア
エレキベア
知っているだけでも迷うことが少なくなりそうクマね

おわりに

マイケル
マイケル
というわけで今日はデザインパターンについて紹介しました!
どうだったかな?
エレキベア
エレキベア
聞いたことあるのもいくつかあって、パターン名と紐づいてきた気がするクマ
エレキベア
エレキベア
でも結局はコードを書いてみるというのが一番クマね
マイケル
マイケル
その通りだね!実際に自分のコードに適用して、効果を実感してみよう!
今後もUnity関連でパターンを適用した例なんかも記事で紹介できたらなと思うよ。
エレキベア
エレキベア
それは楽しみクマ〜〜〜
マイケル
マイケル
それと調べている過程で見つけたんだけど、GitHubでUnityでパターンを適用したサンプルをあげてくれている方がいて、これを見てみるのもすごく勉強になりそうだと思ったよ!

GitHub – QianMo/Unity-Design-Pattern

エレキベア
エレキベア
ありがたいクマ〜〜〜〜〜
マイケル
マイケル
それでは今日はここまで!!
アデュー!!
エレキベア
エレキベア
クマ〜〜〜〜

【ソフトウェア開発】基本のデザインパターン36種類を簡単に整理する【GoF + Game Programming Patterns】 〜完〜

コメント