[保存版]人間が読んで理解できるデザインパターン解説#2: 構造系(翻訳)

#1 作成系デザインパターン #2 構造系デザインパターン(本記事) #3 振舞い系デザインパターン 概要 原著者の許諾を得て、MITライセンスに基づき翻訳・公開いたします。 英語記事: Design Patterns for Humans™ – An ultra-simplified explanation 更新日: 2017/09/25 著者: Kamran Ahmed サイト: Hugobots — 開発者向けのニュースレターを発行しています。 「Design Patterns for Humans」は商標(TM)です。 人間が読んで理解できるデザインパターン解説#2: 構造系(翻訳) 🎉 究極にシンプルなデザインパターン解説! 🎉 誰もがつい心躍ってしまうタイトルにしてみました。タイトルに負けないよう、本記事ではこれ以上不可能なまでにシンプルな方法にこだわってデザインパターンを解説しています。 本ガイドを気に入っていただいた方はコーヒー一杯おごってくださいまし。他の記事も読んでみたい方は、ぜひHugobotsにご登録お願いいたします。 🚀 はじめに デザインパターンとは、常に繰り返される問題を解決するためのものであり「特定の問題に取り組む方法のガイドライン」です。デザインパターンはクラスではありませんし、アプリに追加するだけで奇跡を起こしてくれるようなパッケージやライブラリでもありません。デザインパターンはそうしたものではなく、特定の状況で特定の問題に取り組む方法を示すガイドラインであるとご理解ください。 デザインパターンとは、常に繰り返される問題を解決するためのものであり「特定の問題に取り組む方法のガイドライン」です。 Wikipediaには次のように書かれています。 ソフトウェアエンジニアリングにおけるデザインパターンとは、ソフトウェア設計上の特定コンテキストにおいてよく発生する問題に対する「一般的かつ再利用可能な問題解決法」である。デザインパターンは、ソースコードやマシンコードに直接置換えられるような最終設計ではない。デザインパターンは、さまざまな状況に適用可能な問題解決法の記述、またはテンプレートである。 ⚠️ ご注意 デザインパターンは、あらゆる問題を解決する「銀の弾丸」ではありません。 デザインパターンを強制してはなりません。無理にデザインパターンを適用すれば良くない結果が生じることでしょう。デザインパターンは、問題が起こったときにそれを解決するために使うものであって、問題をあら捜しして解決するものではありません。デザインパターンに過剰な期待を持たないことです。 適切な場所で適切に用いられたデザインパターンは、救いの神になるでしょう。そうでないデザインパターンは荒れ狂い、コードをめちゃめちゃにしてしまうことでしょう。 追伸: 以下のコードサンプルではPHP-7を使っていますが、コンセプトはどの言語でも同じなので、どうかページを閉じないでください。ついでながら、他の言語のサポートについては現在作業中です。 デザインパターンの種別 作成系 構造系 — 本記事 振舞い系 #2 「構造系」デザインパターン わかりやすくまとめるとこうです。 構造系パターンとは、オブジェクトのcomposition(構成)を主眼に据えたものです。言い換えると、どのようにしてエンティティ同士が互いを利用するかを記述します。さらに別の言い方をすると、「ソフトウェアのコンポーネントをどのように組み立てるのか?」という問題に答えるためのものです。 Wikipediaではこうです。 ソフトウェアエンジニアリングにおける構造系パターンとは、エンティティ間の関連付けを実現するシンプルな方法を1つに定めることによって設計を容易にするデザインパターンである。 Adapterパターン Bridgeパターン Compositeパターン Decoratorパターン Facadeパターン Flyweightパターン Proxyパターン 🔌 Adapterパターン(link) 現実世界になぞらえるとこうです。 メモリーカードに画像がいくつか保存されており、これを自分のパソコンにコピーしたいとします。メモリカードをパソコンに挿入して画像を転送するには、自分のパソコンのポートと互換性のある何らかのアダプタが必要です。このカードリーダーが、adapterです。 別の例: 電源プラグにはプラグのピンが3本のものと2本のものがあります。3本タイプのプラグは2本プラグ用のコンセントには挿し込めませんので、挿入するには2本プラグ用コンセントと互換性のある変換アダプタが必要になります。これもadapterです。 さらに別の例: 通訳者は、ある人物の話す言葉を翻訳して、別の人物に伝えます。この通訳者もadapterです。 わかりやすくまとめるとこうです。 adapterパターンとは、互換性のない別のオブジェクトをadapterでラップして、別のクラスとの互換性を得るためのものです。 Wikipediaではこうです。 ソフトウェアエンジニアリングにおけるadapterパターンとは、既存のクラスのインターフェイスを別のインターフェイスとして利用できるようにするものである。adapterパターンは、ソースコードを改変せずに既存のクラスが別のクラスと協調して動くようにさせる目的で頻繁に利用される。 プログラム例 ゲームで考えてみましょう。ここではハンターがライオンを狩るゲームにしました。 最初にLionというインターフェイスを記述します。これにはすべての種類のライオンを実装しなければなりません。 interface Lion { public function roar(); } class AfricanLion implements Lion { public function roar() { } } class AsianLion implements Lion { public function roar() { } } ハンターは、Lionインターフェイスのすべての実装について狩りを行えることを期待します。 class Hunter { public function hunt(Lion $lion) { } } ここで、ゲームにWildDogという野犬を追加しなければならないとしましょう。もちろんこれもハンターが狩りの対象にできることが求められます。しかし野犬のインターフェイスはライオンのと同じではないので、直接狩りの対象にはできません。ハンターとの互換性を得るには、互換性のあるadapterを1つ作成しなければなりません。 // これをゲームに加える必要がある class WildDog { public function bark() { } } // 野犬をadapterでラップして、ゲームとの互換性を得られるようにする class WildDogAdapter implements Lion { protected $dog; public function __construct(WildDog $dog) { $this->dog = $dog; } public function roar() { $this->dog->bark(); } } これで、WildDogAdapterを使えばゲームでWildDogを利用できるようになります。 $wildDog = new WildDog(); $wildDogAdapter = new WildDogAdapter($wildDog); $hunter = new Hunter(); $hunter->hunt($wildDogAdapter); 🚡 Bridgeパターン(link) 現実世界になぞらえるとこうです。 あなたはWebサイトをひとつ所有しているとします。Webサイトにはさまざまなページがあり、ユーザーがテーマを自由に変更できるようにすることを求められているとします。どのようにすればよいでしょうか: テーマの数だけページのコピーを作成しますか?それとも独立したテーマを作成し、ユーザー設定に応じてテーマを読み込ませますか?bridgeパターンを使って、後者のような手法を実現できます。 … Continue reading [保存版]人間が読んで理解できるデザインパターン解説#2: 構造系(翻訳)