Swiftで覚えるデザインパターンその2

# はじめに
前回投稿した[Swiftで覚えるデザインパターン](https://qiita.com/ta9yamakawa/items/4f97855be4bd0698d166)の続きです。

1. **[Swiftで覚えるデザインパターン](https://qiita.com/ta9yamakawa/items/4f97855be4bd0698d166)**
    1. Strategy
    1. Observer
    1. Decorator
    1. Factory Method
    1. Abstract Factory
    1. Singleton
1. **Swiftで覚えるデザインパターンその2** ← 今ココ
    1. Command
    1. Adaptor
    1. Facade
    1. Template Method
1. **[Swiftで覚えるデザインパターンその3](https://qiita.com/ta9yamakawa/items/4d18cabe2c9de4ffe3b9)** `2021/09/09公開`
 1. Iterator
 1. Composite
 1. State
 1. Compound

# Commandパターン
## 概要
リクエスト（操作）を一つのオブジェクトとしてカプセル化する。
これにより、**操作の追加が容易**になったり、**操作を組み合わせて新しい操作**ができる。

大きく以下の4つから成る。

- 具体的なCommandを作成し、そのレシーバの設定をする`Client`
- リクエストに対応するための処理について知っている`Receiver`
- アクションとレシーバを結びつけ、レシーバの処理を実行する`Command`
- コマンドを保持し、呼び出されたコマンドを実行するように依頼する`Invoker`

## 試しに作ったもの
某有名ブラザーズゲームっぽいコントローラー画面を作りました。

お兄ちゃんは、Aを押せばジャンプ、Bを押せばファイアボールをします。
弟くんはAとBで逆のアクションをする変わり者です。

また、お兄ちゃんの方だけ特別にCを押せばジャンプしながらファイアボールをしてくれます。

|<img width="200" alt="CommandSampleApp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/ade4a4d9-3ef6-bcbe-e9fd-3ce3257844e9.png">|
|:--|


|Aを押した時|Bを押した時|Cを押した時|
|---|---|---|
|<img width="110" alt="JumpAction.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/5a3f6e83-9196-3c72-7194-8631b6a432ef.png">|<img width="120" alt="FireballAction.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/6a041417-8d30-0eb1-1a12-61da7fa77c5d.png">|<img width="120" alt="SpecialCommand.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/4af0a7a1-9efa-2502-8dc1-77897135e89c.png">


## クラス図
今回のViewControllerが`Client`役になり、Invoker/具体的なレシーバ/具体的なコマンドを呼ぶ。
`Invoker`は`Command`を呼び出し、格納、削除、リクエストされた時点でのコマンド実行依頼を行う。
`Receiver`はMario、Luigi内にリクエストに対する具体的なアクションを実装していく。

具体的な`Command`で、レシーバのアクションを実行するように処理を記述する。
Commandが呼び出すレシーバによって処理が変更できるし、レシーバが具体的な処理を知っているので他のオブジェクトがそれを知っている必要はなくなる。

|<img width="600" alt="Command.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/f45c3603-693b-3c79-ac4b-d97080df0c73.png">|
|:--|


## 実装

```swift:Receiver周り
protocol Receiver {
    var name: String { get }

    func action(by commandType: CommandType)
}

// ルイージの場合も同様
class Mario: Receiver {
    var name: String = "マリオ"
    
    func action(by commandType: CommandType) {
        let commandText: String
        switch commandType {
        case .A:
            commandText = "プーン"
        case .B:
            commandText = "ボッ"
        }
        print("\(name)「\(commandText)」")
    }
}
```

```swift:Command周り
protocol Command {
    var receiver: Receiver { get }

    func execute()
}

/// コマンドの種類
enum CommandType {
    /// Aボタン
    case A
    /// Bボタン
    case B
}

// 他のコマンドも同様
class JumpCommand: Command {
    var receiver: Receiver

    init(receiver: Receiver) {
        self.receiver = receiver
    }

    func execute() {
        receiver.action(by: .A)
    }
}
```

```swift:Invoker
class CommandInvoker {
    /// コマンド配列
    private var commands: [Command] = []

    /// コマンドを追加する
    func addCommand(with command: Command) {
        commands.append(command)
    }

    /// コマンドを全て削除する
    func removeAllCommands() {
        commands.removeAll()
    }

    /// コマンドを実行する
    func execute() {
        for command in commands {
            command.execute()
        }
    }
}
```

```swift:CommandViewController.swift
class CommandViewController: UIViewController {
    /// Invoker
    private let invoker = CommandInvoker()
    /// Receivers
    private let mario = Mario()
    private let luigi = Luigi()

    // 他のボタンを押した時も同様
    @IBAction func didTapJumpButton(_ sender: Any) {
        let marioJumpCommand = JumpCommand(receiver: mario)
        let luigiJumpCommand = JumpCommand(receiver: luigi)
        action(with: marioJumpCommand)
        action(with: luigiJumpCommand)
    }

    // コマンドの組み合わせを行なっている
    @IBAction func didTapSpecialCommand(_ sender: Any) {
        let jump = JumpCommand(receiver: mario)
        let fireball = FireballCommand(receiver: mario)
        action(with: jump)
        action(with: fireball)
    }

    /// コマンドを実行する
    func action(with command: Command) {
        invoker.addCommand(with: command)
        invoker.execute()
        // 別のコマンドを実行したときのため登録したコマンドを削除しておく
        invoker.removeAllCommands()
    }
}
```

# Adaptorパターン
## 概要
クライアントが必要しているがそのままだと使えないクラスのインターフェースを、別のインターフェースに変換することで利用可能にする。
この変換する役割を持っているものが`アダプタ`である。

クライアントをインターフェースから分離するのでアダプタがインターフェースの変更をカプセル化して、クライアントの変更を不要にする。

また、アダプタには下記の2種類がある。

- **オブジェクトアダプタ**
- **クラスアダプタ**

## 試しに作ったもの
野球選手の、ピッチングとバッティングの動作を、ボタンを押したら表示するようなものを作りました。

|<img width="250" alt="AdaptorSampleApp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/05a23205-aa7b-f879-c455-eddf8ebc3d33.png">|
|:--|


|強打者を押した時|エースを押した時|
|---|---|
|<img width="110" alt="Hitter.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/d12c7d17-ad6f-e1de-b9c1-eb4609791e1c.png">|<img width="120" alt="Pitcher.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/29ce67e2-6812-5bb2-7736-86711c478c1c.png">|

## クラス図
動作自体は同じように見えますが、

強打者：**オブジェクトアダプター**
エースピッチャー**クラスアダプター**

で作成しています。

オブジェクトアダプタはリクエストをアダプティに移譲します。
クラスアダプタは継承を用いることで、アダプターはアダプティのサブクラスになります。

Javaのように多重継承を使えない言語ではオブジェクトアダプタを使うしかなさそうですね。

|<img width="600" alt="Adaptor.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/cea96aff-08c2-403d-47c7-1bd94415bad8.png">|
|:--|

## 実装

```swift:BaseballProtocol.swift
protocol BaseballPlayer {
    func throwing()
    func hitting()
}
```

```swift:ObjectAdaptor
class PowerHitter {
    func homerun() {
        print("ホームラン")
    }
}

class PowerHitterAdaptor: BaseballPlayer {
    let player: PowerHitter

    init(player: PowerHitter) {
        self.player = player
    }

    func throwing() {
        print("送球")
    }

    func hitting() {
        player.homerun()
    }
}
```

```swift:ClassAdaptor
class AcePitcher {
    /// 投球
    func fastBall() {
        print("豪速球")
    }
}

// Adaptor
class AcePitcherAdaptor: AcePitcher, BaseballPlayer {
    func throwing() {
        super.fastBall()
    }

    func hitting() {
        print("打撃")
    }
}
```

```swift:AdaptorViewController.swift
class AdaptorViewController: UIViewController {

    let powerHitter = PowerHitter()

    var pitcherAdaptor: BaseballPlayer?
    var hitterAdaptor: BaseballPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()

        hitterAdaptor = PowerHitterAdaptor(player: powerHitter)
        pitcherAdaptor = AcePitcherAdaptor()
    }

    // throwingButtonも同様
    @IBAction func didTapHittingButton(_ sender: Any) {
        guard let adaptor = hitterAdaptor else {
            return
        }
        adaptor.hitting()
        adaptor.throwing()
    }
}
```

# Facadeパターン
## 概要
複雑になったサブシステムを簡素化して統合するクラスを作成することで、クライアント側で呼びやすくする。

ちなみにFacadeの読み方は**ファサード**。ファケードとかかと思っていた。
Facadeは(建物の)**正面**、(しばしば実体よりりっぱな事物の)**外見、見た目**みたいな意味があるみたいです。

つまり、細かい処理をしているサブシステムたちの処理をファサードに集約させて、クライアントは**窓口**（ファサード）に処理をお願いするようにすればシンプルな実装になり、クライアントとサブシステムが密結合になるのを防ぐことができます。

## 試しに作ったもの
家主が外出中は家電類の電源を切り、帰宅したら全ての家電の電源を入れるような画面を作りました。
中央のスイッチの切り替えで外出/帰宅のステータスを切り替えます。

|<img width="200" alt="FacadeSampleApp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/5175d91d-bb57-81d4-97ee-08fd2faf85e7.png">|
|:--|

|外出中|帰宅時|
|---|---|
|<img width="140" alt="Outsider.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/c2fa57e0-4464-4e26-65b1-241a5a9a3cbb.png">|<img width="140" alt="Backhome.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/12e1ecae-54de-d5bc-6ce4-4df17e3fc377.png">|

## クラス図
今回はスマートスピーカーをFacade代わりにしています。（本来であれば人感センサーとかの方がここでは適切だったりする？笑）
スマートスピーカーが家電系の操作諸々の処理を集約してくれているので、クライアントはサブシステムの処理を知っている必要はありません。

|<img width="600" alt="Adaptor.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/748903bb-63aa-6f37-6968-a75f22f4757f.png">|
|:--|

## 実装
```swift:サブシステム周り
/// 家電の電源On/Off操作プロトコル
protocol HomeAppliances {
    /// 電源をつける
    static func turnOn()
    /// 電源を切る
    static func turnOff()
}

/// TV（照明やスピーカーも同様）
class TV: HomeAppliances {
    static func turnOn() {
        print("TVをつけました")
    }

    static func turnOff() {
        print("TVを消しました")
    }
}
```

```swift:Facade
/// スマートスピーカー（Facadeの役割）
class SmartSpeaker {
    /// 全ての家電の電源をつける
    func turnOnAllHomeAppliances() {
        Light.turnOn()
        TV.turnOn()
        Speaker.turnOn()
    }

    /// 全ての家電の電源を切る
    func turnOffAllHomeAppliances() {
        Light.turnOff()
        TV.turnOff()
        Speaker.turnOff()
    }
}
```

```swift:FacadeViewController.swift
class FacadeViewController: UIViewController {
    /// スマートスピーカー
    private let smartSpeaker = SmartSpeaker()
    /// 家主のステータスを操作するスイッチ
    @IBOutlet private weak var toggleSwitch: UISwitch!

    @IBAction func didToggleSwitch(_ sender: Any) {
        if toggleSwitch.isOn {
            smartSpeaker.turnOnAllHomeAppliances()
        } else {
            smartSpeaker.turnOffAllHomeAppliances()
        }
    }
}
```

# Template Methodパターン
## 概要
メソッド内のアルゴリズムの骨組みを定義し、その手順のいくつかをサブクラス側で再定義させる。

これにより得られる恩恵としては以下が考えられます。

- 大元のアルゴリズムを変更する必要がなくなる。
- 同様のクラスを作成する場合は「いくつかの手順」のみを定義するだけで良くなる。

## 試しに作ったもの
二人の新卒社員による自己紹介をしてもらう画面です。
ボタンを押せばそれぞれのあいさつを確認できます。

|<img width="240" alt="TemplateMethodSampleApp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/5a99d482-ea54-7792-883f-1cededb806cb.png">|
|:--|

|田中さん|山田さん|
|---|---|
|<img width="260" alt="Tanaka.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/ebd483cf-ddc7-f6fa-3b7a-3d6d06ac9dc9.png">|<img width="260" alt="Yamada.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/ac45f698-ee41-0fc5-1c6a-163cacff6ab8.png">|

## クラス図
`SelfIntroduction`がJavaで言う`Abstract Class（抽象クラス）`に当たりますが、Swiftには抽象クラスを定義できないので、protocol extensionを用いて実現させます。

テンプレート部分の抽象メソッドは具象クラス（Tanaka, Yamada）で実装することでそれぞれの自己紹介を作成するようにします。

|<img width="550" alt="TemplateMethod.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/600b30ea-436f-cdca-3db6-ee3b6eb0fc81.png">|
|:--|


## 実装
```swift:テンプレート
protocol SelfIntroduction {
    /// 名前
    func name()
    /// 職業
    func job()
}

extension SelfIntroduction {
    /// 自己紹介
    func introduction() {
        greet()
        name()
        job()
        enthusiasm()
    }

    /// 最初の一言
    func greet() {
        print("こんにちは！")
    }

    /// 意気込み
    func enthusiasm() {
        print("頑張ります！よろしくお願い致します。")
    }
}
```

```swift:各社員
// 山田さんの場合も同様
class Tanaka: SelfIntroduction {
    func name() {
        print("田中です！")
    }

    func job() {
        print("エンジニアやってます。")
    }
}
```

```swift:TemplateMethodViewController.swift
class TemplateMethodViewController: UIViewController {
    /// 田中さん
    private let tanaka = Tanaka()
    /// 山田さん
    private let yamada = Yamada()

    @IBAction func didTapTanakaButton(_ sender: Any) {
        tanaka.introduction()
    }

    @IBAction func didTapYamadaButton(_ sender: Any) {
        yamada.introduction()
    }
}
```

# おさらい
| パターン | 特徴 |
|:-----------|:-----------|
| Command | リクエスト(操作)を一つのオブジェクトとして作成する。 これにより高い拡張性や再利用性を担保できる。|
| Adaptor | クライアントが使えないインターフェースを扱えるインターフェースの形に変換する。 |
| Facade | 複雑なサブシステムの処理を一つのインターフェースに統合する。これによりクライアントはインターフェースを呼び出すだけで良くなる。 |
| Template Method | 骨組みの決まったアルゴリズムの内の「ある手順」をサブクラスに再定義させる。 アルゴリズムの大きな構造を変えずに細かい処理を修正できるようになる。|

今回は4つのデザインパターンについて学びました。
実際に作ったアプリ（クラス図画像付き）は前回の記事同様、[GitHubのリポジトリ](https://github.com/ta9yamakawa/DesignPatterns)で公開していますので、具体的な実装をみたい方がいらっしゃったらご覧ください。
投稿したQiitaの記事ごとにディレクトリを分けているので、今回の実装は`Patterns2`に含まれております。

Facadeパターンとかは結構シンプルで覚えやすいですが、CommandパターンやAdaptorパターンは地味に複雑な構造という印象を受けたので使わないと忘れてしまいそうですね(汗

ここ違くないか？みたいな指摘やこうすれば覚えやすいよみたいなアドバイス等があればぜひコメントをいただきたく思います。
いただいたコメントを踏まえて、学びをより深いものにして行けたらと思っております✨

# 参照
**共通**
[Head Firstデザインパターン ―頭とからだで覚えるデザインパターンの基本](https://www.amazon.co.jp/Head-First%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3-%E2%80%95%E9%A0%AD%E3%81%A8%E3%81%8B%E3%82%89%E3%81%A0%E3%81%A7%E8%A6%9A%E3%81%88%E3%82%8B%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%81%AE%E5%9F%BA%E6%9C%AC-Eric-Freeman/dp/4873112494)

**Commandパターン**

1. [Command – 野生のプログラマZ](http://harumi.sakura.ne.jp/wordpress/2018/12/10/command/)
1. [【Commandパターン】GUIイベント処理や履歴管理で用いるデザインパターン【コード例：Java】](https://debimate.jp/2021/01/09/%E3%80%90command%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%80%91gui%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E5%87%A6%E7%90%86%E3%82%84%E5%B1%A5%E6%AD%B4%E7%AE%A1%E7%90%86%E3%81%A7%E7%94%A8%E3%81%84%E3%82%8B/)

**Adaptorパターン**

1. [Swiftで学ぶデザインパターン9 (Adapterパターン) - しめ鯖日記](https://llcc.hatenablog.com/entry/2015/07/11/235101)
1. [Swiftを使用してデザインパターンまとめ 2.Adapterパターン](https://qiita.com/kanda_227/items/32705d904f906a8eea43)

**Facadeパターン**

1. [Facade – 野生のプログラマZ](http://harumi.sakura.ne.jp/wordpress/2018/12/01/facade/)
1. [15．Facadeパターン | TECHSCORE(テックスコア)] (https://www.techscore.com/tech/DesignPattern/Facade.html/)

**Template Methodパターン**
[【Swiftでデザインパターン】TemplateMethod - Qiita](https://qiita.com/yosshi4486/items/747ec38cf066de523996)