プログラミング学習を進めていると「デザインパターン」というワードが出てきますが、しっかりと学習したことがない方も多いのではないでしょうか。
本記事では、Javaのようなオブジェクト指向開発で利用されるデザインパターン全23種の概要についてご紹介していきます。
デザインパターンって何?
デザインパターンは、オブジェクト指向で設計する際の内容を、利用される内容別に分類した設計パターンを指しています。
GoFのデザインパターン
デザインパターンは広義の意味では、設計におけるパターンであれば該当しますが、よく使われるデザインパターンの意味として「GoF」のデザインパターンがあります。
Gang of Fourと呼ばれる4人により執筆された書籍を元に、全23種の設計パターンが割り振られています。
デザインパターンといえば「GoFのデザインパターン」を指すというほど一般化してきており、オブジェクト指向設計における基礎知識の1つです。
デザインパターンのメリット
デザインパターンを利用するメリットとしては、「設計における共通知識として使える」ことや「再利用性が高い実装が出来る」、「コードの可読性が上がりメンテナンスがしやすくなる」などがあげられます。
設計者が自由に設計を進めてしまうと、設計者の意図を正確に汲み取ることは難しいですが、デザインパターンに沿って設計を行うことで共通認識を持った状態で開発を進めることが可能です。
またデザインパターンが出来上がるまでに様々なエンジニアが試行錯誤を繰り返してきた経緯もあるため、信頼性の高い開発が出来るのもメリットです。
デザインパターンの種類
GoF おデザインパターンは全部で23種類に分けられており、それぞれが「生成」「構造」「振る舞い」の3つの大カテゴリーに分けることが出来ます。
- 生成
- Abstract Factory
- Builder
- Factory Method
- Prototype
- Singleton
- 構造
- Adapter
- Bridge
- Composite
- Decorator
- Facade
- Flyweight
- Proxy
- 振る舞い
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
各デザインパターンの概要を知ろう
各デザインパターンについての概要を抑えておきましょう。
良く使うパターンと滅多に登場しないパターンがありますので、全体像としてこんなパターンがあるんだと把握することが大切です。
生成
生成のデザインパターンでは、オブジェクト作成に関するデザインパターンとして、インスタンス化やグループ化時の制御方法が提言されています。
Abstract Factory
関連するオブジェクトを生成する処理を集約化して、オブジェクトの追加や変更を簡単に行えるようにするパターンです。
Abstractの名前の通り、具体的な処理内容には触れずインターフェース部分にのみ着目します。
Builder
Builderパターンは複数オブジェクトを作成する際に有効で、オブジェクトの作成過程を抽象化することで、バリエーションの異なるオブジェクトの生成が可能です。
Factory Method
Factory Methodパターンでは、オブジェクトを生成する部分を集約化させるパターンで、クラスに変更が起きた際の影響を小さく抑えられることが出来ます。
また変更だけでなく、機能追加する場合にも役立ちます。
Prototype
Prototypeパターンでは、クラスからインスタンスを生成するのではなく、インスタンスからインスタンスのコピーを作成する方法です。
インスタンス生成のために複雑な処理が必要だったりする場合に、Prototypeパターンを用いることで簡単に複製が可能となります。
Singleton
1つのクラスからオブジェクトを1つだけ生成させるデザインパターンがSingletonです。
複数のインスタンスを生成させたくないような処理で利用されます。
インスタンスが1つしか存在しないことが保証される代わりに、クラス間の結合が強まってしまうことを意識する必要があります。
構造
構造系パターンでは、エンティティ間の関連付けに着目し、どのようにお互いを利用するか、どのようにしてシステムを組み立てるかが提言されています。
Adapter
Adapterパターンでは、元々関連性のないクラス同士を必要な形にラップすることにより、関連付けを行いお互いに利用出来るようにする方法です。
既存のクラスをラップして利用することになるため、素早く必要な機能を作成することが可能となります。
Bridge
Bridgeパターンでは、「機能追加」と「機能実装」のクラス層を繋げる役割を果たす方法です。
機能クラスと実装クラスを分けることにより、独立性が高まり拡張がしやすくなります。
Composite
入れ物となるクラスと実体となるクラスを抽象クラスを利用して1つにまとめ、同一視出来るようにするのがCompositeパターンです。
同一視させることにより、利用者側からは入れ物か実体かを意識する必要がなくなります。
Decorator
オブジェクトに対してデコレーション(飾り付け)を行い機能拡張していく方法がDecoratorパターンです。
飾り付けを行うオブジェクトには一切手を加えることなく、飾り付けるオブジェクトにより機能を追加していくことが可能です。
Facade
複雑に関連を持っているクラス群に窓口を設けることで、シンプルに利用出来るようにする方式がFacadeパターンです。
窓口となるインターフェース用のクラスを用意しておくことで、様々なクラスを制御する必要がなくなります。
Flyweight
インスタンスをなるべく共有することで、無駄なメモリの使用を防止するのがFlyweightパターンです。
メモリ使用量を抑えることに加えて、インスタンス作成の回数を減らすことも出来るためパフォーマンスの向上も期待出来ます。
Proxy
proxyの言葉通り、代理を置いて本体の負担を減らすのがProxyパターンです。
本体以外でも出来る仕事を代理のオブジェクトに任せることで、本体のオブジェクトに掛かる負担を軽減させることが可能です。
振る舞い
それぞれのオブジェクトがどのような振る舞いを行うかを提言したデザインパターンについても確認していきましょう。
Chain of Responsibility
日本語で責任の連鎖となるように、自身が処理出来るオブジェクトが見つかるまで要求を流していくのがChain of Responsibilityパターンです。
複数のオブジェクトで鎖のように関係性を持たせ、利用者側はいずれかのオブジェクトに要求するだけで自動的に処理出来るオブジェクトに要求を回してくれるようになります。
Command
命令を1つのオブジェクトとして管理するのがCommandパターンです。
1つのオブジェクトで管理することにより、追加や削除・実行といった処理管理がしやすくなり、再利用もしやすくなります。
Interpreter
規則を持ったクラスを作成し、規則に沿った命令を実行させるのがInterpreterパターンです。
Interpreterパターンでは、1つの規則を1クラスで記述するのが原則です。
Iterator
あるグループの要素に対し、順にアクセスする方式を規則化するのがIteratorパターンです。
Iteratorパターンを採用することで、実装と切り離した上で繰り返しパターンを仕組み化することが出来ます。
Mediator
仲介オブジェクトを配置することにより、オブジェクト間のやりとりを少なくさせる方式がMediatorパターンです。
各オブジェクトは相談役と呼ばれる仲介オブジェクトとのみやりとりすることで、仲介役から各オブジェクトへ命令が行われます。
Memento
オブジェクトを任意の状態で保持することで、後で元の状態に戻すことが出来る方式を提供するのがMementoパターンです。
テキストエディタなどで利用出来るundo機能を提供します。
Observer
オブジェクトを監視することで、状態が変化した際に通知を行うのがObserverパターンです。
観察対象のオブジェクトが変化したタイミングで、定義しておいた処理を実施することが出来ます。
State
状態をクラスとして切り出すことで、クラスを切り替えることにより状態変化を表現するのがStateパターンです。
状態遷移図の状態をそのままクラスとして表現することが出来るため、処理が分かりやすくなります。
Strategy
Strategyパターンでは、アルゴリズムの実装部分を状況に応じてまるごと切り替えられる方式です。
利用者側は意識することなく、アルゴリズムを切り替えることで処理の効率化を図ります。
Template Method
スーパークラスでは処理の枠組みだけを作成し、実際の処理はサブクラスで実装させるのがTemplate Methodパターンです。
基盤となる処理はスーパークラスにまとめた上で、サブクラスで細かな処理を記述することで、基盤の処理が変更になった場合でもサブクラス1つ1つを修正する必要がなくなります。
Visitor
EntryクラスとVisitorクラスを作成し、構造と処理を切り分けるのがVisitorパターンです。
入れ物となるEntryクラスはあくまで要求を受け入れるだけなので、処理を追加したい場合でもVisitorクラスを増やせば対応出来るようになります。
さいごに: デザインパターンを学習してJavaのシステム開発に活かそう
本記事では、Javaで利用されるデザインパターンの概要についてご紹介してきました。
デザインパターンは抽象的なものなので、自分の中でしっかりと理解出来るまでには時間が掛かってしまうかも知れません。
他の人が書いたコードを読む際に、どんなデザインパターンが使われているのか意識しながら少しずつ自分の中で理解できるように学習してみましょう。