デザインパターンについて紹介

# はじめに
株式会社エアークローゼットのプロダクトグループでエンジニアをしているVictoryと申します。
この記事は<a href="https://qiita.com/advent-calendar/2022/air-closet">エアークローゼット Advent Calendar 2022</a>の６日目の記事になります。

アプリやウェブの開発をする時どこかデザインパターンと似ているやり方にあったことがあるかもしれません。しかし、その概念を詳しく分かりません。この記事にはデザインパターンの基本について解説していきましょう。
![design-patterns.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2957540/5459efa8-1995-c6d7-b7fa-7a50e760f3b2.jpeg)

# ① デザインパターンとは？
デザインパターンは、オブジェクト指向プログラミングのテクニックです。これは非常に重要であり、優れたプログラマーは知っておく必要があります。 デザインパターンは、OOP言語で頻繁に使用されます。 プログラミングでよく遭遇する一般的な問題の解決策である「設計パターン」を提供します。 私たちが直面している問題を考え出す解決策は最適ではないかもしれません. デザインパターンは、最適な方法で問題を解決するのに役立ち、OOPプログラミングのソリューションを提供します。

デザインパターンはプログラミング言語ではありません。 Java、C#、Javascript、その他のプログラミング言語など、ほとんどのプログラミング言語で実行できます。

"各パターンは、何度も発生する問題を説明し、その問題の解決策の核心を、考えずに何度でも使用できるように示しています。"  — Christopher Alexander —

# ② なぜデザインパターンが必要？
デザインパターンは、コードの再利用に役立ち、簡単に拡張できます。

これは、ソフトウェア エンジニアリングの問題を解決するための最適化された実績のあるソリューションのコレクションです。したがって、問題に直面する場合、デザインパターンは、問題の解決策を自分で見つけるのではなく、問題を解決するための実証済みのガイドとなります。

デザインパターンは一般的な形でソリューションを提供し、テストモデル、テストされた開発モデルを提供することでソフトウェア開発をスピードアップするのに役立ちます.

デザインパターンを再利用すると、重大なバグを引き起こす可能性のある潜在的な問題を回避するのに役立ち、後で簡単にアップグレードして保守できます。

プログラマーが他の人のコードをすばやく理解できるように支援します (コミュニケーションとして理解できます)。すべてのチームメンバーは、時間をかけずにプロジェクトを構築するために互いに簡単にコミュニケーションを取ることができます。

# ③ いつデザインパターンを使用するべき？
プログラムを本当にシンプルに保ちたい時、デザインパターンを使用すると、解決済みの問題の解決策を考える時間と労力を削減できます。

# ④ デザインパターンの書類
1994 年に、Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides の4人の著者が、プログラミング ソフトウェアにおけるデザインパターンの概念の起源である、Design Patterns – Elements of Reusable Object-Oriented Software というタイトルの本を出版しました。

この4人の作家は、ギャング オブ フォーとして広く知られています。 4人の観点から、デザインパターンは主に以下のオブジェクト指向設計のルールに基づいています。
　・インターフェイスを実装するのではなく、インターフェイス用にプログラムします。
　・継承 (inheritance) よりもオブジェクト合成 (包含) を優先します。
![design-patterns-classify.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2957540/74429659-9418-f5df-2dee-d1cac32df353.png)
デザインパターンのシステムには現在、「再利用可能なオブジェクト指向ソフトウェアのデザインパターンの要素」の本で定義されている 23 のパターンがあり、次の 3 つのグループに分けられます。
　・Creational(初期化グループ - 5 パターン) には、Factory Method、Abstract Factory、Builder、Prototype、Singleton が含まれます。この種のデザインパターンは、Newメソッドを使用してオブジェクトを直接作成する代わりに、オブジェクトを作成し、その作成のロジックを非表示にするソリューションを提供します。これにより、特定の状況でどのオブジェクトを作成するかを決定する際に、プログラムがより柔軟になります。
　・Structural(構造グループ - 7 パターン) には、Adapter、Bridge、Composite、Decorator、Facade、Flyweight、Proxy が含まれます。このタイプのデザイン パターンは、クラスとオブジェクト メンバーに関連しています。オブジェクト間の関係を確立および定義するために使用されます。
　・Behavioral (相互作用/行動のグループ – 11 パターン) には、Interpreter, Template Method, Chain of Responsibility, Command, Iterator, Mediator, Memento, Observer, State, Strategy và Visitorが含まれます。このグループは、オブジェクトの動作、オブジェクト間の通信を実装するために使用されます。

下の図は、23 の基本的なデザイン パターン間の関係を示しています。
![design-patterns-relationship.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2957540/cff6cc22-5c4c-80ef-21cd-db54c4178e3d.jpeg)

### 4.1 Creationalグループ(初期化グループ)

![Creational.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2957540/000a26b6-24c5-b427-8ac5-5f38057644f8.png)

・Singleton（シングルトン）:
クラスのインスタンスが 1 つだけであることを確認し、そのクラスへのグローバル アクセス ポイントを提供します。
使用頻度：★★★★中程度。

・Abstract Factory（アブストファクトリー）:
各オブジェクトを作成するときにクラスを指定したり、具象クラス (concrete) を定義したりせずに (関連する) オブジェクトを作成するためのインターフェイスを提供します。
使用頻度：★★★★★高め。

・Factory Method（ファクトリー　メゾット）:
オブジェクトを作成するためのインターフェイスを定義するが、オブジェクトの作成に使用するクラスをサブクラスに決定させる Factory メソッドにより、クラスはオブジェクトの初期化プロセスをサブクラスに渡すことができます。
使用頻度：★★★★★高め。

・Builder（ビルダー）:
複雑なオブジェクトの構築をその表現から切り離して、同じ構築プロセスで異なる表現を生成できるようにします。
使用頻度：★★中程度。

・Prototype（プロトタイプ）:
このテンプレート オブジェクトをコピーして作成された、テンプレート オブジェクトを使用して作成されるオブジェクトのタイプを指定します。
使用頻度：★★★中。

### 4.2 Structuralグループ
![Structural.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2957540/cd39d1ed-4ec9-c6c8-1460-4c0df60c0bbb.png)

・Adapter(アダプター):
互換性の問題により、クラスのインターフェースを、クラスのユーザー要件に適合する別のインターフェースに変更してください。
使用頻度：★★★★中程度。

・Bridge（ブリッジ）:
問題のセマンティクスを実装から分離することの目的は、両方の部分 (セマンティクスと実装) を個別に変更できるようにすることです。
使用頻度：★★★中。

・Composite（コンポジット）：
ツリーのような階層でオブジェクトを編成します。構造内のすべてのオブジェクトは、同等に同種の方法で操作されます。
オブジェクト間の包括的な階層関係を作成します。クライアントは、含まれているオブジェクトと含まれているオブジェクトを同じものとして見ることができます -> クライアントのコードの一般化可能性 -> 開発、アップグレード、および保守が容易です。
使用頻度：★★★★中程度。

・Decorator（デコレータ）:
実行時に (動的に) オブジェクトに追加の責任を割り当てます (機能を拡張します)。
使用頻度：★★★中。

・Facade（ファサード）：
「サブシステム」内の一連のインターフェイスに単一のインターフェイスを提供します。サブシステムを使いやすくするために、既存のものの上にインターフェイスを定義します。
使用頻度：★★★★★高め。

・Flyweight（フライウエート）：
共有を使用して、多数の「小さな」オブジェクト (段落、行、列、文字など) を効率的に処理します。
使用頻度：★少ないです。

・Proxy（プロキシ）:
別のオブジェクトを表すオブジェクトを提供して、そのオブジェクトへのアクセスをサポートまたは制御します。置換オブジェクトはプロキシと呼ばれます。
使用頻度：★★★★中程度。

### 4.3 Behavioralグループ
![Behavioral.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2957540/b32051d8-a776-ed9c-09a7-211cbac5cb0f.png)

・Chain of Responsibility（チェーン　オフ　ライアビリティー）:
メッセージの送信者と受信者の間のペアリングを修正します。メッセージを受信するオブジェクトは文字列に連結され、メッセージは、それを処理するオブジェクトに到達するまで、このチェーンに沿って渡されます。複数のオブジェクトが要求を処理できるようにすることで、要求送信要素と要求受信および処理要素の間のハード バインディングを回避します。要求を受け取るオブジェクトをチェーンにリンクし、特定のハンドラーが検出されるまで、各ハンドラーを介して要求を送信します。
使用頻度：★★中程度。

・Command（コマンド）:
各リクエスト (何かを行う) はオブジェクトにラップされます。リクエストは保存され、オブジェクトとして送信されます。リクエストをオブジェクトにカプセル化して、リクエストを受信し、リクエストに対してソート、ログ、元に戻すなどの操作を実行するプログラムをパラメータ化できるようにします。
使用頻度：★★★★中程度。

・Interpreter（通訳者）：
言語の文法表現とインタープリターの定義をサポートします。
使用頻度：★少ない。

・Iterator（イテレータ）:
要素の内部表現に依存せずに、コレクション オブジェクトの要素 (リスト、配列など) に順番にアクセスします。
使用頻度：★★★★★高め。

・Mediator（メディエーター）:
複数のオブジェクト間の通信をラップするオブジェクトを定義します。
使用頻度：★★中程度。

・Memento（メメント）:
データ ラップを壊すことなく、オブジェクトの内部状態を変更して返します。
使用頻度：★少ない。

・Observer（オブザーバー）:
オブジェクト間の 1 対多の依存関係を定義して、オブジェクトの状態が変化すると、その依存オブジェクトもすべて変化するようにします。
使用頻度：★★★★★高め。

・State（ステータス）：
オブジェクトの内部状態が変化したときにオブジェクトの動作を変更できるようにすると、オブジェクトのクラスが変更されたように感じられます。
使用頻度：★★★中。

・Strategy（ストラテジー）：
アルゴリズムのファミリをオブジェクト クラスでラップして、アルゴリズムを使用するプログラムとは無関係にアルゴリズムを変更できるようにする. アルゴリズムのファミリを提供すると、クライアントはアルゴリズムを使用するときに特定のアルゴリズムを動的に選択できる.
使用頻度：★★★★中程度。

・Template method（テンプレートのメソッド）:
アルゴリズムのフレームワーク、つまり基本クラスに実装されていないいくつかのメソッドを呼び出す汎用アルゴリズムを定義します。派生クラスの委譲メソッドの実装。
使用頻度：★★★中。

・Visitor（ビジター）：
構造を定義するクラスを変更せずに、オブジェクト構造の要素に作用する新しい操作を定義できます。
使用頻度：★少ない。

# ⑤ デザインパターンを勉強するため前提知識
デザインパターンを上手に学ぶには、OOP の 4 つの特徴である継承、ポリモーフィズム、抽象化、カプセル化をマスターする必要があります。

次は、インターフェイスとアブスト（抽象）という 2 つの概念があります。これは非常に重要です。これら 2 つの概念を理解して適用するには時間がかかる場合がありますが、コツをつかめば、本当に必要であることがわかります。

構造的思考を放棄し、完全に OOP の考え方を受け入れます。

上記をマスターしたら、できるだけ早くデザインパターンの学習を開始する必要があります。 

# ⑥ どこで勉強する？
＊本：
　・Design Patterns: Elements of Reusable Object-Oriented Software
　・Head First Design Patterns
　・Design Patterns For Dummies
　・Pattern Hatching: Design Patterns Applied.
　・Refactoring to Patterns.
　・Patterns of Enterprise Application Architecture.

＊デザインパターンのサイト：
　・https://sourcemaking.com/design_patterns
　・https://refactoring.guru
　・https://www.tutorialspoint.com/design_pattern/index.htm
　・https://www.javatpoint.com/design-patterns-in-java
　・http://www.oodesign.com/
　・http://java-design-patterns.com
　・http://www.javacamp.org/designPattern/
　・https://en.wikipedia.org/wiki/Software_design_pattern
　・dotNet Design Patterns: https://www.dofactory.com/net/design-patterns
　・Javascript Design Patterns: https://www.dofactory.com/javascript/design-patterns

# ⑦ どやって勉強する？
デザインパターンをよく学ぶには、次の 3 つの部分に注意を向けてください。

・いつ使用され、デザインパターンはどのような問題を解決しますか?
・UMLダイアグラムは、デザインパターンを記述します。
・図示されたコード、その実用的なアプリケーション等は何ですか?

# ⑧ 最後
デザインパターンは、ソフトウェアのプログラミング、構築、設計の経験を表しています。 システムの適切なデザイン パターンを理解して適用する人は、多くの時間と労力を節約し、開発、拡張、保守が容易になります。 ただし、使いすぎてはいけません。

次のことを覚えておく必要があります。
・デザインパターンは、問題を解決するための記述またはパターンです。 最終的なデザインではありません。
・デザインパターンは、問題を複雑にするためではなく、問題を解決するために作成されます。
・デザインパターンは、コードの最適化、再利用、理解、アップグレードと修復を容易にするのに役立ちます。

この記事を通じて、誰もがデザインパターンとその利点をよりよく理解できることを願っています。 フィードバックや提案をお待ちしております。

<a href="https://qiita.com/advent-calendar/2022/air-closet">エアークローゼット Advent Calendar 2022</a>はまだまだ続きますので、ぜひ他のエンジニア, デザイナー, PMの記事もご覧いただければと思います。

次回は@nghia11110さんが担当しますので、是非お楽しみに！