TypeScriptで学べるデザインパターン ~デザインパターンとは？~

# デザインパターンとは？
デザインパターンは、ソフトウェア開発における<font color="Red">**よくある問題に対する再利用可能な解決策**</font>のことです。
もっと簡単に言うと、**抽象化の方法**をまとめたものになります。

例えば、「パンダ」「猫」「さかな」という3つの単語があった時に、
生物に注目 ⇨ 「パンダと猫」|「さかな」(哺乳類と魚介類)
関係に注目 ⇨ 「猫とさかな」|「パンダ」(猫はさかなを食べる)
文字に注目 ⇨　「パンダとさかな」|「猫」（3文字と2文字）
という3通りのくくり方ができます。

<img width=350 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554678/de0bac7a-cb16-0105-bda0-ca30ae25215a.png">

デザインパターンはプログラミングにおいて、**オブジェクトのどこに注目してまとめるのか？** についてよくある解法をまとめた便利ツールになります。

# デザインパターンの歴史

もともとは建築業界において、「よくある問題」に対する「解決策のパターン」を集めたガイドラインが起源でした。

1980年代からオブジェクト指向設計の普及とともに、ソフトウェアにおいても再利用可能な設計が求められるようになりました。
そこで、1994年、**エリック・ガンマ（Erich Gamma）** 、**リチャード・ヘルム（Richard Helm）** 、**ラルフ・ジョンソン（Ralph Johnson）**、**ジョン・ヴリシディス（John Vlissides）** の4人による著作『デザインパターン: オブジェクト指向ソフトウェアの再利用（Design Patterns: Elements of Reusable Object-Oriented Software）』が発表されました。タイトルからも分かるように、デザインパターンは再利用性に重点をおいたプログラミングの設計になっています。ちなみにこの作者4人は「Gang of Four（GoF）」として知られています。

## 「Gang of Four（GoF）」のイメージ
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554678/19e1c00d-737f-fcc2-12c0-7e45b973decd.png">

## 実際のGang of Four
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554678/dd5c6be9-494c-798e-18f8-c0166108e8ee.png">


# デザインパターン一覧

GoFの本に紹介されている全23パターンの特徴をまとめました。

## 1. オブジェクトの生成に関するパターン
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554678/ec29defd-563b-4d2a-b31b-c51ae3ffddff.png">

| パターン名 | 説明 | 例 |
| ----- | ----- | --- |
| Singleton | クラスのインスタンスが1つだけであることを保証し、グローバルなアクセスポイントを提供。 | 設定管理、ログ管理 |
| Factory Method | インスタンス化をサブクラスに委譲するためのインターフェースを提供。 | 形状の生成 (円、四角形など) |
| Abstract Factory | 関連または依存するオブジェクトのファミリを生成するためのインターフェースを提供。 | UIテーマ (MacOS, Windows) |
| Builder | 複雑なオブジェクトの生成プロセスを分離し、異なる表現を可能にする。 | 家具構築、HTMLビルダー |
| Prototype | 既存のオブジェクトをコピーして新しいインスタンスを生成。 | ゲーム内キャラクター複製 |

 ## 2. オブジェクトの構造に関するパターン
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554678/01a42464-9101-247b-ebea-e4a8262084e7.png">

| パターン名 | 説明 | 例 |
| --- | --- | --- |
| Adapter | クラスのインターフェースをクライアントが期待する別のインターフェースに変換。 | 旧APIと新APIの接続 |
| Bridge | 実装から抽象化を分離して、それぞれ独立して拡張可能にする。 | UI描画システム |
| Composite | オブジェクトをツリー構造で扱い、個々のオブジェクトとコンポジットオブジェクトを同一視。 | ファイルシステム構造 |
| Decorator | オブジェクトに動的に新しい機能を追加。 | GUIコンポーネント拡張 |
| Facade | 複雑なシステムへの簡易なインターフェースを提供。 | サードパーティライブラリ |
| Flyweight | メモリを節約するために、多くのオブジェクトで共有可能なデータを再利用。 | 文字オブジェクト (フォント) |
| Proxy | 実際のオブジェクトへのアクセスを制御。 | リモートプロキシ、キャッシュ |

## 3. オブジェクトの振る舞いに関するパターン
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554678/3463c8f3-3dbb-3f0c-0f1d-943953f80e5d.png">

| パターン名 | 説明 | 例 |
| --- | --- | --- |
| Chain of Responsibility | リクエストを複数のハンドラーが順番に処理できるようにする。 | ログ処理、UIイベント |
| Command | 要求をオブジェクトとしてカプセル化し、要求をパラメータ化、キューイング、ロギング可能に。 | Undo/Redo機能 |
| Iterator | コレクション内の要素を順番に走査する方法を提供。 | 配列やリストの反復処理 |
| Mediator | オブジェクト間の通信を仲介するオブジェクトを提供し、オブジェクト同士の結合を減らす。 | チャットルーム |
| Memento | オブジェクトの状態を保存し、後でその状態を復元できるようにする。 | Undo機能、ゲームの進行状況の保存 |
| Observer | オブジェクトの状態変化を他のオブジェクトに通知。 | イベントリスナー |
| State | オブジェクトが状態に応じて異なる振る舞いをするようにする。 | ファイルの状態 (開く/閉じる) |
| Strategy | アルゴリズムをオブジェクトとしてカプセル化し、交換可能にする。 | 並べ替えアルゴリズム |
| Template Method | スーパークラスでアルゴリズムの骨格を定義し、サブクラスで具体的な処理を実装。 | ゲームフレームワーク |
| Visitor | オブジェクト構造に新しい操作を追加。 | 構文木のトラバース |


# デザインパターンのメリット

## コードの品質向上
- 再利用性の向上
デザインパターンを活用することで、実証済みの解決策を再利用できるようになります。これにより、冗長なコードを削減し、開発時間を節約できます。

- メンテナンス性の向上
デザインパターンを使用すると、コードがよりモジュール化され、保守が容易になります。開発者はアプリケーション全体に影響を与えることなく、特定の部分を変更できるため、トラブルシューティングやアップデートが簡素化されます。

- 拡張性の向上
デザインパターンは柔軟な構造を提供し、変化するニーズに対応して将来の拡張を容易にします。これにより、大規模なアーキテクチャの変更なしにソフトウェアシステムを成長させることができます5。

## 開発プロセスの効率化
- コミュニケーションの円滑化
デザインパターンは開発者間の共通言語となり、ソフトウェアアーキテクチャの理解と効果的なコミュニケーションを促進します。これにより、チームメンバー間のシームレスな協力が可能になります。

- 問題解決の効率化
デザインパターンは一般的な設計問題に対する実証済みの解決策を提供します。これにより、開発者は低レベルの実装の詳細に煩わされることなく、ドメイン固有の問題解決に集中できます。

## 設計の標準化
- 一貫性とベストプラクティスの促進
デザインパターンは、共通の設計問題に対する標準化された解決策を提供することで、一貫性とベストプラクティスを促進します。これにより、開発チームは共通の語彙と指針を確立し、チームメンバー間のコミュニケーション、協力、知識共有を促進できます

# デザインパターンのデメリット

## 「もしあなたが金槌しか持ってなければ、すべてが釘に見える。」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554678/bd055657-0ddc-d1db-2429-8a464f854920.png)

無理にデザインパターンを当てはめようとすると、無駄に複雑なコードが出来上がってしまい保守性が下がります。

以下の「複雑性の増加」「学習コスト」「過剰適用」がデザインパターンのデメリットとして挙げられます。

- 複雑性の増加
デザインパターンを適用することで、コードの構造が複雑になる可能性があります。特に、Abstract Factory パターンなどの導入により、システムの全体的な複雑さが増す場合があります。

- 学習と適用の難しさ
デザインパターンを効果的に使いこなすまでには、相当な時間と経験が必要です。パターンの構造を知っていることと、実際にそれを適切に適用できることは別問題です。

- 過剰適用のリスク
新しく学んだデザインパターンを無理に適用しようとする傾向があります。不適切な場面でパターンを使用してしまう可能性があります。

# デザインパターンが学べるサイト

- [Refactoring Guru](https://refactoring.guru/ja/design-patterns)
簡単な文章とわかりやすい例で各デザインパターンを説明しています。C#、C++、Go、Java、PHP、Python、Ruby、Rust、Swift、TypeScriptなど多くの言語でのサンプルコードも提供されています。
<img width=150 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554678/8f1c7eec-8569-75e3-cd7a-c66d0487f65e.png">

(謎のたぬきのキャラクターがいる)



- [TECHSCORE](https://www.techscore.com/tech/DesignPattern/)
GoFの23個のデザインパターンをJavaを使って解説しています。デザインパターンの基本事項から各パターンの詳細な説明まで網羅しています

- [Structural Design Pattern in TypeScript Series' Articles](https://dev.to/jmalvarez/series/20586)

# デザインパターンが学べる書籍

- 『[Java言語で学ぶデザインパターン入門](https://amzn.asia/d/bAyf4dt)』(結城浩 著)
<img width=200 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554678/d2fab6c6-ba5b-6bd9-518d-4991315f5f30.png">

GoFの23のデザインパターンをJavaを使って分かりやすく解説しています。初心者にも理解しやすい説明と図解が特徴。


- 『[Head Firstデザインパターン](https://amzn.asia/d/bNg0bux)』(Eric Freeman, Elisabeth Robson 著)
<img width=200 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554678/3eafa793-cf6b-113e-4133-0b9959c39260.png">

イラストや会話形式を多用し、楽しみながらデザインパターンを学べる本です。

- 『[オブジェクト指向における再利用のためのデザインパターン](https://amzn.asia/d/5GmqhNz)』(通称:GoF本)

<img width=200 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554678/04061f19-23a4-394b-19c0-25c657e21abf.png">

デザインパターンの原典とも言える本で、23のパターンを詳細に解説しています。難解です。。。

# 最後に
2024年のアドベントカレンダーの完走賞をもらうためにデザインパターンを学習し始めましたが、**「意外と難しくないかも！」** というのが印象でした。
名前は仰々しくて難しそうですが、考え方は「共通する部分をまとめる」など普段の業務でも行っている基本的な考え方だと感じました。
なるべく初心者向けにわかりやすくデザインパターンについて解説しているので、お役に立てると嬉しいです！