# Javaデザインパターン忘備録
1. Iterator
ループがデータに依存せずに行える。
Listだろうが、配列だろうが、Setだろうが、何だろうが同じような呼び出しになる。
2. Adapter
既存のクラスで実装された機能を別のクラスで使いたい時に、型変換を行い、使いたい型でその機能を使えるようにする。
3. Template Method
継承を利用して、細かい違いをサブクラスで表現しつつ、大筋のロジックを共通化できる
4. Factory Method
共通のFactoryインターフェイスとProductインターフェイスを使ってメインのプログラムを実装することにより、工場の具体的な種類(インターフェイスに実装)を変えるだけで、生成される商品の挙動を変化させることができる。
5. Singleton
クラスのインスタンスを一つだけに限定できる。
6. Prototype
あらかじめ各クラスのインスタンスを、まとめ役(Prototype役)に登録しておくことで、必要なインスタンスをまとめ役に登録されたインスタンスからコピーして作成することができる。
- インスタンスを作成する際に、new Somethingとプログラム本体に書く必要を無くなる。
- 多くのクラスをまとめて管理できる。
- 生成の難しいインスタンスをコピーにより生成できる。
7. Builder
Template Methodに似ているが、これは継承ではなく委譲を利用しており、細かい違いをそれぞれ表現したクラスのメソッドを用いて、大筋のロジックを組み立てている。結果として、ロジックを共通化できる
8. Abstract Factory
何かを作りたい時(例えばhtmlファイルなど)に利用。
その作りたいものを構成する部品を作成するメソッドのインターフェイスは決まっており、そのメソッドを好きな引数で好きな回数呼び出して作りたいものを作成する。
その作りたいものを構成する部品を作成するメソッドの実装は実装クラスに任せることで、違いを表現できたり、変更に強くすることができる。
例えばhtmlの作成で。リンクの部品をクリックすると、同じタブで遷移するか新しいタブでリンクを開くかなどは、実装クラスを変えることで表現できる。
9. Bridge
機能のクラスと実装のクラス(細かい違い)を分けることができる。
すなわち、実装クラス用の共通のインターフェイスを用いて、機能のクラスではロジックを組み立てている。
こうすることで、機能追加の際には機能のクラスを追加すればよく、挙動(実装)を変更したい場合は実装クラスを変更すれば良いことになる。
10. Strategy
アルゴリズムのみを委譲によって切り替えることができる。
これにより、inputに対するoutputの算出方法を気軽に切り替えることができる。
例えば、「高速だが正確性に欠けるアルゴリズム」と「低速だが正確なアルゴリズム」を場面によって使い分けることができる。
11. Composite
容器(複数)と中身(単数)の同一視ができるようにする。
例えば、HashMapの実装で、基本は各ハッシュ値に対して中身(単数)が対応するようにするが、衝突が起きた際には、そのハッシュ値に容器(複数)を入れることで対応する。
12. Decorator
同じインターフェイスを実装したクラスならば、委譲によって何度でも機能追加を行えるようにする。
イメージは、シールドを張った人に、
- 炎無力化バリアを追加
- 水無力化バリアを追加
- 一定時間経過で回復するバリアを追加
を考える際に、追加する際は一つ前の状態にそのまま追加でき、最終的には全ての機能を取得した人が誕生する、というイメージ。
java.ioのInputStreamReader、BufferReader、FileReaderなどはこのパターンが使われている。
13. Visitor
データ構造と処理を分離。
データ構造を表現したクラスに対し、処理を行うクラス(実装によって何をするかは異なる)を与えると、委譲によってその処理を行うメソッド呼び出し、データの処理を行う。
14. Chain of Responsibility
処理を委譲によってたらい回しにする。
Handlerの役(処理役)は自分ができる処理のみを行い、自分の手に追えないものは次のクラスに処理を託す。
プログラム動作中に処理を行うクラスを変更することも可能。
デメリットとして、処理が遅くなる可能性あり。
15. Facade
インターフェイスを少なくし、一つの機能を表現する為に、一つのメソッドを呼べば済むようにする。具体的な他のクラスを呼んで行ったりする処理はFacade役に集約される。
16. Mediator
状態変化のロジックを一つのクラスにまとめる。
委譲を利用することにより、状態変化に応じて対象クラスの処理を呼び出す。
17. Observer
状態変化に応じた処理の記述に有効。
Subject(被験者)の役に各Observer(観察者)の役を登録し、Subjectの中の状態が変化した際には委譲を通じてObserverの対象メソッドを呼び出す。
18. Memento
インスタンスの状態を保存したい時に用いる。
Originator役は自分の状態を保存したい時にMemento役を作成し、Caretaker役の判断により以前Mementoに保存した状態に戻る。この時、カプセル化の破壊が起こらないよう、Memento役はOriginator役にはインターフェイスを広くし(パッケージを同じにするなどして)、Caretaker役にはインターフェイスを狭くする。(呼び出し可能なメソッドを少なくする。)
19. State
状態をクラスで管理。オーバーロードにより、if文などの条件分岐を用いずに状態に基づいた処理を記述することができる。
20. Flyweight
インスタンスを共有し、無駄にnewしない。インスタンスを必要とする場合には、そのFactoryクラスから生成し、そのFactoryクラスでは、すでにインスタンスが存在する場合には、そのインスタンスをそのまま使うようにする。これにより、メモリやnewにかかる時間(コンストラクタの処理にかかる時間)を節約できる。
21. Proxy
Subject役が重い処理を行うクラスのとき、その代理としてProxy役を用意する。Proxy役とSubject役はインターフェイスを共有し、なるべくProxy役が処理を行うことにより、ギリギリまでSubject役を利用しない。HTTPプロキシーのように、クライアントからの要求に対し、キャッシュが存在しない場合のみサーバに情報を取りに行くというようなイメージ。
22. Command
処理命令を1つのインスタンスとして管理。
命令の履歴管理が可能になる。
具体的には、詳細な命令を記述したクラスと、それら命令をjava.util.Stackで保存し管理するクラスを用意する。
どちらも同じインターフェイスを用いる。
23. Interpreter
Java言語を使って、目的に応じた簡単な言語を作成する。
正規表現やバッチ処理言語を記述可能。