今回はエンジニアに欠かせない設計ノウハウである、GoFのデザインパターン。
このページでは、概要がざっとわかるように記載します。
GoFのデザインパターンの概要
そもそもデザインパターンとは?
たくさんプログラミングをしていると、「こう設計しておけばよかった」ということがよくあります。
「こう設計しておくと、後々便利である」という経験則を言語化してまとめたものがデザインパターンです!
設計における「おばあちゃんの知恵」みたいな感じです。
GoFのデザインパターンとは?
Gang of Fourと呼ばれる4名によって設計されたデザインパターンです。
全部で23種類あります。
「デザインパターン=Gofのデザインパターン」と認識されるほど、有名なデザインパターンたちです。
どんなものがあるの?
おおよその役割に基づいて、
- 生成
- 構造
- 振る舞い
の3つのパターンに分類されます。
ひとまずは名前をご紹介します。
生成に関するパターン
- Singleton
- Factory Method
- Abstract Factory
- Builder
- Prototype
構造に関するパターン
- Adapter
- Facade
- Bridge
- Composite
- Decorator
- Flyweight
- Proxy
振る舞いに関するパターン
- Iterator
- State
- Strategy
- Template Method
- Chain of Responsibility
- Command
- Interpretor
- Mediator
- Memento
- Observer
- Visitor
数が多すぎるし、名前だけじゃ分からない。
ということで、それぞれざっくりどういうものかをご紹介します。
ざっくり把握した後、詳しく知りたくなったら各ページ詳細ページにアクセスしてみてください。
※詳細ページは現在執筆中です。
各パターンの概要
生成に関するパターン
Singleton
1つのクラスからは、1つのオブジェクトのみを生成させる、というパターンです。
複数のインスタンスを作らないコードとなります。
インスタンスを1つのみにするので、クラス間の結合が強まってしまいます。
グローバルを多用したりするので、嫌う人も一定数います。
※個人の肌感です。
Factory Method
オブジェクトの生成とオブジェクトの具体的な処理を分離するパターンです。
クラス変更の影響範囲を小さくするために用いられます。
単一責任の原則を満たしているのが分かりますね。
Abstract Factory
Factory Methodパターンをより複雑にしたものです。
関連するオブジェクトを生成する処理を、抽象化して集約化するパターンです。
複数の部品を組み合わせて、1つに作り上げるパターンです。
例えば、「今日のコーディネートどうしよう?」というときに、トップスは〇〇でボトムスは××で~、靴は△△を履こう!みたいに考えますよね。
こんな感じで、オブジェクトの追加や、変換を簡単に行えるようにするために用いられます。
抽象度を高くして、具体的な処理には触れないインターフェースクラスを作成します。
Builder
オブジェクトの作成過程を抽象化するパターンです。
複数のオブジェクトを作成するのに有効で、バリエーションの異なるオブジェクト生成が可能になります。
Prototype
クラスからインスタンスを作成するのではなく、インスタンスからインスタンスのコピーを作成できるパターンです。
いわゆる「ディープコピー」、つまり全く同じものを複製できるという機能がこれに当たります。
日常生活で例えると、「コピペ」の機能を実装する、といった感じです。
インスタンス生成の処理が複雑な処理の場合、Prototypeパターンが有効です。
構造に関するパターン
Adapter
関連性のないクラスたちを使いやすい形でwrapすることによって、使いやすくするパターンです。
したがって、別名Wrapperパターンとも呼ばれたりします。
インターフェースを整えるのに使われたりします。
USB type-Cの充電器の先っちょだけを変えて、iPhoneのライトニングで使えるようにするアレのイメージです。
既存のコードを利用したいが、そのままでは使いにくいときにも使います。
Facade
カタカナではファサードと書きます。
複雑な関連性を持っているクラスたちに簡単な呼び出しクラスをつくるようにし、シンプルに扱えるようにするパターンです。
APIやAPIラッパーみたいに、いろいろ処理をしてくれるクラスというイメージでもいいかもしれません。
Bridge
機能の実装クラスと追加クラスを別に作成し、それを関連付けるクラスも作成するパターンです。
実装クラスと機能クラスを分けるので独立性は高まり、それぞれは拡張しやすくなります。
しかし、クラスが増えるので、設計管理が大変になったりもします。
WindowsとMacで動かせるようにするときなどに使われますが、基本あまり使われなかったりします。
Composite
クラスを木構造で設計していくパターンです。
ディレクトリをtreeで出力したときの木構造をイメージしてください。
このようにして階層構造を作成していきます。
Decorator
デコるパターンです。
嘘です。
オブジェクトに対して、飾りつけを行いながら機能拡張をしていくパターンです。
別のクラスが持っている特定の機能を、別のクラスに追加していきます。
「Twitter通知」クラスと「Slack通知」クラスの通知機能を合算した「TwitterとSlack通知」機能を持ったクラスのようなイメージです。
そして、そういえば最近デコるって聞きませんね。。。。
Flyweight
インスタンスの数を最小限に、出来るだけ共有するパターンです。
無駄なメモリ使用を防止するために用いられます。
キャッシュによく用いられています。
メモリ使用が減るので、おおよそ高速化します。
※最小限にすることで、変な処理を書いてしまうと本末転倒になります。
Proxy
特定のクラスに代わって処理を行うクラスをを作成します。
自身が処理できなかった時に、デフォルトの処理を呼ぶ、みたいな感じです。
SubjectクラスはRealSubjectクラスとProxyクラスを同一視して利用するためのインターフェースです。
振る舞いに関するパターン
Iterator
特定のグループの要素に対して順にアクセスするようなパターンです。
複雑な繰り返し処理を、簡単に呼び出せるようにします。
State
状態をクラスとして切り出し、この状態変えることで処理を変えるパターンです。
具体的には、同じメソッド内でif文で分岐処理するのではなく、状態に応じた処理をクラスごとに作成し、どのクラスで処理をするかを変化させます。
状態遷移図からクラスに落とし込むことができるような実装になります。
Strategy
アルゴリズムの実装を、使う場合に応じて切り替えられるようにするパターンです。
Stateは状態をクラスとして切り出すのに対し、Strategyは種別やタイプ別のクラスを抽象クラスでラップするような形になります。
Stateはライフサイクルの中で状態が可変であり、Strategyは状態は不変であるような形になります。
Template Method
処理の枠組みはスーパークラスで呼び出し、実際の処理は子クラスで実装するパターンです。
処理が変更になったとき、変更するのは実際の処理を変更しているクラスのみで良くなります。
Stategyパターンは型の継承と委譲を使って処理を抽象化するのに対し、Template Methodは実装の継承を使って抽象化します。
継承は強すぎる関連と判断する際には、Strategyパターンを使用します。
Chain of Responsibility
難しい名前の通り、処理できるオブジェクトが見つかるまで深ぼっていくパターンです。
処理実装者は大変ですが、それを利用する側は何か1つを操作すればよいので、利用する側が簡単になります。
単一責任の処理クラスを、処理が終わるまで次々作成していきます。
Command
命令系統を1つのオブジェクトとして管理するパターンです。
追加、削除、変更を加えるのはこのオブジェクトからアクセスすればいいので、利用者も書く方もわかりやすくなります。
Interpreter
これは名前通り、規則に沿った命令を実行させるパターンです。
HTMLやXMLなどの構文を翻訳するクラスというとイメージしやすいでしょうか。
原則として、1つの規則を1つのクラスで実装します。
Mediator
直訳すると、「仲裁人」という意味です。
オブジェクト間の仲裁役、つまりデータの受け渡しを行います。
これにより、オブジェクトの独立性が高まります。
Memonto
オブジェクトを任意の状態で保存できるようにするパターンです。
あとから元の状態に戻すことができます。
ctrl+Zのイメージです。
Observer
オブジェクトの状態を監視し、状態変化の際に通知を行うようにするパターンです。
イベントハンドラみたいなイメージです。
Visitor
EntryクラスとVisitorクラスを実装し、構造と処理を分けるパターンです。
要求を受け入れるのがEntryクラスで、実際の処理はVisitorクラスで実装します。
処理を追加したい場合は、Visitorクラスを増やすようにメンテしていきます。
Commandパターンのコマンド受け入れと、処理実装を2つに分割したようなイメージです。
まとめ
今回はUMTP UMLで問われる設計スキル、GoFのデザインパターンをまとめてみました!
これは実際の業務にもかなり役立ってくると思います!
いかがでしたでしょうか!
クラス図が足りないところがあるので、随時足していきます!
ご指摘、ご質問あればtwitterまでお問い合わせください!
最後までお読みいただきありがとうございます!!!