Javaデザインパターン – 例チュートリアル

紹介

デザインパターンはソフトウェア開発者の間で非常に人気があります。デザインパターンは、共通のソフトウェアの問題に対するよく説明された解決策です。

デザインパターンを使用する利点の一部は次のとおりです:

  1. デザインパターンはすでに定義されており、再発する問題を解決するための業界標準のアプローチを提供するため、デザインパターンを適切に使用すれば時間を節約できます。Javaベースのプロジェクトで使用できる多くのJavaデザインパターンがあります。
  2. デザインパターンを使用すると、再利用性が向上し、より堅牢で高度に保守可能なコードが生まれます。ソフトウェア製品の総所有コスト(TCO)を削減するのに役立ちます。
  3. デザインパターンがすでに定義されているため、コードが理解しやすくデバッグしやすくなります。これにより、開発が迅速化し、チームの新メンバーもそれを簡単に理解できます。

Javaデザインパターンは、生成構造、および行動デザインパターンの3つのカテゴリに分かれています。

この記事は、すべてのJavaデザインパターン記事の索引として機能します。

生成デザインパターン

創造的なデザインパターンは、特定の状況においてObjectを最適な方法でインスタンス化するためのソリューションを提供します。

1. Singletonパターン

Singletonパターンは、Classのインスタンス化を制限し、Java仮想マシン内にクラスのインスタンスが1つだけ存在することを保証します。Singletonパターンの実装は、常に開発者の間で議論の的となっています。

注意: Singletonデザインパターンについて詳しく学びましょう。

2. Factoryパターン

Factoryデザインパターンは、複数のサブクラスを持つスーパークラスがあり、入力に基づいてサブクラスのいずれかを返す必要がある場合に使用されます。このパターンは、クライアントプログラムからClassのインスタンス化の責任をファクトリクラスに移します。ファクトリクラスにはシングルトンパターンを適用するか、ファクトリメソッドをstaticにすることができます。

注意: Factoryデザインパターンについて詳しく学びましょう。

3. 抽象ファクトリーパターン

抽象ファクトリーパターンは、ファクトリーパターンに類似しており、ファクトリーのファクトリーです。もしJavaでファクトリーデザインパターンに慣れているなら、単一のファクトリークラスがあり、入力に基づいて異なるサブクラスを返すことに気付くでしょう。そして、そのファクトリークラスはこれを達成するためにif-elseswitchステートメントを使用します。抽象ファクトリーパターンでは、if-elseブロックを取り除き、各サブクラスに対するファクトリークラスと、入力ファクトリークラスに基づいてサブクラスを返す抽象ファクトリークラスがあります。

注意: 抽象ファクトリーパターンについて詳しく学びましょう。

4. ビルダーパターン

ビルダーパターンは、オブジェクトが多くの属性を含む場合のファクトリーおよび抽象ファクトリーデザインパターンのいくつかの問題を解決するために導入されました。このパターンは、多数のオプションパラメーターと一貫性のない状態の問題を解決し、オブジェクトを段階的に構築し、実際に最終的なObjectを返す方法を提供します。

注意: ビルダーパターンについて詳しく学んでください。

5. プロトタイプパターン

プロトタイプパターンは、Objectの作成にコストがかかり、多くの時間とリソースが必要であり、類似したObjectが既に存在している場合に使用されます。このパターンは、元のObjectを新しいObjectにコピーして、必要に応じて変更するメカニズムを提供します。このパターンでは、Javaのクローンを使用してObjectをコピーします。プロトタイプデザインパターンは、コピーしているObjectがコピー機能を提供する必要があることを義務付けています。他のクラスによって行われてはいけません。ただし、オブジェクトのプロパティのシャローコピーまたはディープコピーを使用するかどうかは、要件に依存し、設計上の決定です。

注意: プロトタイプパターンについて詳しく学んでください。

構造設計パターン

構造設計パターンは、異なる方法でClass構造を作成するためのものです(たとえば、継承やコンポジションを使用して小さなObjectから大きなObjectを作成する方法など)。

1. アダプターパターン

アダプター設計パターンは、構造設計パターンの1つであり、2つの関連のないインターフェースが一緒に動作できるように使用されます。これらの関連のないインターフェースを結合するオブジェクトをアダプターと呼びます。

注意:アダプターパターンについて詳しくはこちらをご覧ください。

2. コンポジットパターン

コンポジットパターンは、部分全体の階層を表現する必要がある場合に使用されます。構造を作成する必要があり、構造内のオブジェクトを同じ方法で処理する必要がある場合は、コンポジット設計パターンを適用できます。

注意:コンポジットパターンについて詳しくはこちらをご覧ください。

3. Proxyパターン

プロキシパターンは、別のObjectに対するアクセスを制御するためのプレースホルダーを提供します。このパターンは、機能への制御されたアクセスを提供したい場合に使用されます。

注意: Proxyパターンについて詳しく学ぶ。

4. Flyweightパターン

フライウェイトデザインパターンは、Classの多くのObjectを作成する必要がある場合に使用されます。各Objectはメモリスペースを消費しますが、これは低メモリデバイス(モバイルデバイスや組み込みシステムなど)にとって重要です。フライウェイトデザインパターンは、Objectを共有することでメモリ負荷を軽減するために適用できます。

JavaでのStringプールの実装は、フライウェイトパターンの実装の最良の例の1つです。

注意: Flyweightパターンについて詳しく学ぶ。

5. ファサードパターン

ファサードパターンは、クライアントアプリケーションがシステムと簡単にやり取りできるようにするために使用されます。

注意: ファサードパターンについて詳しく学びましょう。

6. ブリッジパターン

インターフェースと実装の両方にインターフェース階層がある場合、ブリッジデザインパターンが使用され、インターフェースを実装から分離し、クライアントプログラムから実装の詳細を隠します。ブリッジデザインパターンの実装は、継承よりも組み合わせを優先するという概念に従います。

注意: ブリッジパターンについて詳しく学びましょう。

7. デコレーターパターン

デコレーターデザインパターンは、オブジェクトの機能をランタイムで修正するために使用されます。同時に、同じクラスの他のインスタンスには影響を与えません。したがって、個々のオブジェクトが修正された動作を取得します。デコレーターデザインパターンは、構造デザインパターンの1つであり(アダプターパターン、ブリッジパターン、またはコンポジットパターンなど)、抽象クラスまたはインターフェースを使用して構成を実装します。オブジェクトの動作を拡張するには継承または構成を使用しますが、これはコンパイル時に行われ、クラスのすべてのインスタンスに適用されます。ランタイムで新しい機能を追加したり、既存の動作を削除したりすることはできません。これはデコレーターパターンが有用な場合です。

注意: デコレーターパターンについて詳しく学びます。

振る舞いデザインパターン

振る舞いパターンは、オブジェクト間の相互作用を改善し、拡張性と柔軟性を提供する方法を提供します。

1. テンプレートメソッドパターン

テンプレートメソッドパターンは、振る舞いのデザインパターンであり、メソッドスタブを作成し、実装のいくつかのステップをサブクラスに遅延させるために使用されます。テンプレートメソッドは、アルゴリズムを実行するためのステップを定義し、すべてまたは一部のサブクラスに共通のデフォルトの実装を提供することができます。

注意: テンプレートメソッドパターンについて詳しく学びます。

2. メディエーターパターン

メディエーターデザインパターンは、システム内の異なるオブジェクト間の中央集権的な通信媒体を提供するために使用されます。オブジェクトが直接相互作用する場合、システムコンポーネントは互いに密接に結合されているため、保守性コストが高く、容易に拡張することができません。メディエーターパターンは、オブジェクト間の通信用の中央媒体を提供し、オブジェクト間の疎結合を実装することに焦点を当てています。メディエーターはオブジェクト間のルーターとして機能し、通信の手段を提供するための独自のロジックを持つことができます。

注意: メディエーターパターンについて詳しく学びます。

3. 責任連鎖パターン

責任連鎖パターンは、クライアントからの要求が一連のオブジェクトに渡されて処理されるソフトウェア設計において、疎結合を実現するために使用されます。その後、連鎖内のオブジェクトは、要求を処理するのにどのオブジェクトが適切かを決定し、要求を次のオブジェクトに送る必要があるかどうかを決定します。

私たちは、try-catchブロックコード内に複数のcatchブロックを持つことができることを知っています。ここで、各catchブロックは、特定の例外を処理するためのプロセッサのようなものです。したがって、tryブロックで例外が発生すると、最初のcatchブロックに送信されて処理されます。 catchブロックがそれを処理できない場合、要求は連鎖内の次のObject(つまり、次のcatchブロック)に転送されます。さらに、最後のcatchブロックでも処理できない場合、例外は連鎖の外部に投げられ、呼び出しプログラムに渡されます。

注意: 詳細は、責任連鎖パターンを参照してください。

4. オブザーバーパターン

観察者デザインパターンは、Objectの状態に興味があり、変更があるたびに通知を受け取りたいときに便利です。観察者パターンでは、他のObjectの状態を監視するObjectobserverと呼び、監視されているObjectsubjectと呼びます。

Javaは、java.util.Observableクラスとjava.util.Observerインターフェースを介して観察者パターンを実装するための組み込みプラットフォームを提供しています。ただし、実装が制限されているため広く使用されておらず、Javaはクラスでの複数の継承を提供していないため、観察者パターンを実装するためだけにクラスを拡張したくない場合がほとんどです。Java Message Service(JMS)は、アプリケーションが他のアプリケーションにデータをサブスクライブおよびパブリッシュできるようにするために、観察者パターンと調停者パターンを使用しています。

注意: Observer Patternについて詳しく学ぶ。

5. Strategy Pattern

ストラテジーパターンは、特定のタスクに複数のアルゴリズムがある場合や、クライアントが実行時に使用する実際の実装を決定する場合に使用されます。ストラテジーパターンはポリシーパターンとも呼ばれます。複数のアルゴリズムを定義し、クライアントアプリケーションに使用するアルゴリズムをパラメータとして渡します。

このパターンの最高の例の1つは、Collections.sort()メソッドです。このメソッドはComparatorパラメータを取ります。コンパレータインターフェースの異なる実装に基づいて、オブジェクトは異なる方法でソートされます。

注意: ストラテジーパターンについて詳しく学びます。

6. コマンドパターン

コマンドパターンは、リクエスト-レスポンスモデルで疎結合を実装するために使用されます。このパターンでは、リクエストは呼び出し者に送信され、呼び出し者はそれをカプセル化されたコマンドオブジェクトに渡します。コマンドオブジェクトは、特定のアクションを実行するために受信者の適切なメソッドにリクエストを渡します。

注意: コマンドパターンについて詳しく学びます。

7. ステートパターン

状態デザインパターンは、内部の状態に基づいて動作を変更する必要があるときに使用されます。オブジェクトの状態に基づいてオブジェクトの動作を変更する場合、オブジェクトに状態変数を持ち、状態に基づいて異なるアクションを実行するために `if-else` 条件ブロックを使用できます。状態パターンは、これをコンテキストと状態の実装を介して体系的かつ疎結合な方法で実現するために使用されます。

注意: 状態パターンについて詳しく学ぶ。

8. 訪問者パターン

訪問者パターンは、類似した種類のオブジェクトのグループで操作を実行する必要がある場合に使用されます。訪問者パターンを使用すると、オブジェクトから操作ロジックを別のクラスに移動できます。

注意: 訪問者パターンについて詳しく学ぶ。

9. インタプリターパターン

インタプリターパターンは、言語の文法的表現を定義し、この文法を扱うインタプリターを提供するために使用されます。

10. イテレーターパターン

イテレーターパターンは、振る舞いパターンの1つであり、オブジェクトのグループをトラバースするための標準的な方法を提供するために使用されます。イテレーターパターンは、Javaコレクションフレームワークで広く使用されており、イテレーターインターフェースがCollectionをトラバースするためのメソッドを提供しています。このパターンは、私たちの要件に基づいてさまざまな種類のイテレーターを提供するためにも使用されます。イテレーターパターンは、Collectionをトラバースする実際の実装を隠し、クライアントプログラムがイテレーターメソッドを使用します。

注意: イテレーターパターンについて詳しく学びます。

11. メメントパターン

メメントデザインパターンは、オブジェクトの状態を保存して後でそれを復元したい場合に使用されます。このパターンは、オブジェクトの保存された状態データがObjectの外部からアクセスできないように実装されています。これにより、保存された状態データの整合性が保護されます。

Mementoパターンは、2つのObjectoriginatorcaretakerで実装されています。オリジネータは保存および復元する必要があるObjectであり、内部クラスを使用してObjectの状態を保存します。内部クラスは「Memento」と呼ばれ、他のオブジェクトからアクセスできないようにprivateになっています。

その他のデザインパターン

GoFデザインパターンには含まれない多くのデザインパターンがあります。ここでは、これらの人気のあるデザインパターンのいくつかを見てみましょう。

1. DAOデザインパターン

データアクセスオブジェクト(DAO)デザインパターンは、データ永続性ロジックを別レイヤーに切り離すために使用されます。 DAOは、データベースと連携するシステムを設計する場合に非常に人気のあるパターンです。 アイデアは、サービスレイヤーをデータアクセスレイヤーから分離することです。 これにより、アプリケーション内のロジックの分離を実装します。

注意: DAOパターンについて詳しく学びます。

2. 依存性注入パターン

依存性注入パターンを使用すると、ハードコーディングされた依存関係を削除し、アプリケーションを疎結合にし、拡張可能かつ保守可能にすることができます。Javaで依存性注入を実装して、依存関係の解決をコンパイル時から実行時に移動させることができます。Springフレームワークは依存性注入の原則に基づいて構築されています。

注意: 依存性注入パターンについて詳しくは、詳細を学びます。

3. MVCパターン

Model-View-Controller(MVC)パターンは、Webアプリケーションを作成するための最も古いアーキテクチャルパターンの1つです。

結論

この記事ではJavaデザインパターンを要約しました。

Javaデザインパターンの例コードは、当社のGitHubリポジトリから確認できます。

さらにJavaのチュートリアルで学習を続けましょう。

Source:
https://www.digitalocean.com/community/tutorials/java-design-patterns-example-tutorial