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

# はじめに
デザインパターンについて、下記の書籍を用いて勉強したのですが、普段はSwiftでのコーディングをするので実際にクラス図を書いたり実装したりして学ぼうと思いアウトプットしてみました。

[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)
<br>
ボリュームがあるので複数回に分けて記事を投稿予定です。

1. **Swiftで覚えるデザインパターン** ← 今ココ
    1. Strategy
    1. Observer
    1. Decorator
    1. Factory Method
    1. Abstract Factory
    1. Singleton
1. **[Swiftで覚えるデザインパターンその2](https://qiita.com/ta9yamakawa/items/a3e72372df7b2922315b)** `2021/08/20公開`
    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

# Strategyパターン
## 概要
一連の振る舞いを**一連のアルゴリズム**として定義し、それぞれをカプセル化して**交換できる状態にする**。
こうすることで、使用する側に意識をさせることなく簡単に戦略（Strategy）を切り替えられる。

## 試しに作ったもの
画面を開くと自動的にポケモンたちに飛行アクションをさせるというものを作りました。
飛行アクションをする前に、各ポケモンに飛行タイプを定義させます。

今回は下記タイプを用意しました。
- 通常飛行
- 飛行できない
- 風船

## クラス図
`Pokemon`クラスは`FlyBehavior`（飛ぶ振る舞い）を持っている。
Pokemonクラスを継承した`Pikachu`や`Charizard（リザードン)`に実際に`fly`を実行させるためには、`setFlyType`で飛行タイプをセットしてそれによってどのアルゴリズムを使うかを決める。

飛行タイプを決めるのは呼ぶ側で、今回で言うと`StrategyViewController`が2体のポケモンを準備して飛ばそうとしています。

|<img width="900" alt="Strategy.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/b36f3be7-0183-bd5d-a1d1-b86004484067.png">|
|:--|

## 実装

必要そうな部分を抜粋（以降のパターンの実装も同様です。）
実装は参考書籍のものに極力寄せています。

```swift:アルゴリズム
protocol FlyBehavior {
    /// 飛ぶ
    static func fly()
}

class FlyNormal: FlyBehavior {
    static func fly() {
        print("ふつーな飛行")
    }
}
// FlyNoWay, FlyBalloonも同様
```

```swift:Pokemon.swift
class Pokemon {
    enum FlyType {
        case normal
        case noFly
        case balloon
    }
    /// 飛行タイプ
    private var flyType: FlyType?

    /// 飛行タイプを設定
    /// - Parameter type: FlyType
    func setFlyType(with type: FlyType = .normal) {
        flyType = type
    }

    /// 飛行アクション
    func fly() {
        guard let type = flyType else {
            fatalError("飛行タイプが設定されていません")
        }
        switch type {
        case .normal:
            return FlyNormal.fly()
        case .noFly:
            return FlyNoWay.fly()
        case .balloon:
            return FlyBalloon.fly()
        }
    }
}
```

```swift:StrategyViewController.swift
class StrategyViewController: UIViewController {    
    let pikachu = Pikachu()
    let charizard = Charizard()

    override func viewDidLoad() {
        super.viewDidLoad()

        setup()
        fly()
    }

    /// それぞれのポケモンに飛行タイプを指定
    func setup() {
        pikachu.setFlyType(with: .noFly)
//        pikachu.setFlyType(with: .balloon)
        charizard.setFlyType()
    }

    /// 飛行
    func fly() { 
        pikachu.fly() // 「飛べないよぉ」（.noFlyではなく、.balloonにすると「ふわふわ飛ぶよ」みたいに変わる）
        charizard.fly() // 「ふつーな飛行」
    }
}
```

飛行タイプを変えるだけでflyの処理を簡単に切り替えられますね。
※`StrategyViewController.swift`の`setup()`内のコメントアウト部分

# Observerパターン
## 概要
あるオブジェクトの**状態が変わった**ことを、**依存している全てのオブジェクトに自動的に通知して更新**する。

値を保持する`Subject`とそれを監視（購読）する`Observer`から成る。
SubjectとObjectの依存関係は`1:N`である。

## 試しに作ったもの
今回は**購読**って響きからサブスクサービスの**Netflix**的なのを想定しました。
「New episode」を押したらランダムな作品の第n話が発行され、その時Subjectを購読しているユーザに発行した値を通知するような画面を作ってみました。

|<img width="200" alt="ObserverSampleApp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/aee4c1b7-6cd3-a81f-d893-075e0ef6d6de.png">|
|:--|

わかりやすいように、「New episode」を押したら「New Episode Released！」と表示されるようにしています。
ObserverはNetflixに登録（Register）していないと購読できず、逆に購読をやめる(Remove)と購読解除できます。

デバッグ画像は、下記流れの各状態で新しいエピソードを発行したときの結果です。

1. 誰も購読していない
1. Johnだけ購読を始めた
1. Paulも購読を始めた
1. Johnが購読解除した

<img width="400" alt="ObservePrint.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/a2906db4-c69b-f25b-6367-d28966198f88.png">

発行された値をちゃんと登録しているオブザーバーのみが検知できていると思います。

## クラス図
`Subject`と`Observer`のオブジェクトは**疎結合**なので、互いにやりとりできますが中身を知っておくのが不要になるのがポイントのようです。

疎結合によって下記恩恵が得られます。

- Subject, Observer共に、**変更しても影響を及ぼさない**
- Subject, Observer共に**再利用**ができる
    - `HuluSubject`を作ることも考えられる
    - `Taro`がオブザーバとして追加できることも考えられる

|<img width="700" alt="Observer.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/a36ac213-c365-15f0-fec2-47cf30389eb3.png">|
|:--|


## 実装

```swift:Subject周り
protocol Subject: AnyObject {
    /// オブザーバーの登録
    func add(observer: Observer)
    /// オブザーバーの削除
    func remove(observer: Observer)
    /// 新しい値の発行
    func notify()
}

class NetfilxSubject: Subject {
    /// 購読者のリスト
    var observers: [Observer] = []
    /// 作品名
    private var title: String?
    /// 第何話
    private var episode: Int?

    func add(observer: Observer) {
        observers.append(observer)
    }

    func remove(observer: Observer) {
        guard let index = observers.firstIndex(where: {$0.name == observer.name}) else {
            return
        }
        observers.remove(at: index)
    }

    func notify() {
        guard
            let title = title,
            let episode = episode else {
            return
        }

        for observer in observers {
            observer.update(with: title, episode: episode)
        }
    }

    // 作品のデータを用意
    func setNewData(with title: String, episode: Int) {
        self.title = title
        self.episode = episode

        // オブザーバーに通知
        notify()
    }
}
```

```swift:Observer周り
protocol Observer: AnyObject {
    /// 名前
    var name: String {get}
    /// 値の更新
    /// - Parameter title: タイトル
    /// - Parameter episode: エピソード（話数）
    func update(with title: String, episode: Int)
}

// Paulも同様
class John: Observer {
    var name = "John"

    init(with subject: Subject) {
        subject.add(observer: self)
    }

    func update(with title: String, episode: Int) {
        print("John watched: \(title), episode: \(episode)")
    }
}
```

```swift:ObserverViewController
class ObserverViewController: UIViewController {
    private let subject = NetfilxSubject()
    private var john: John?
    private var paul: Paul?
    /// 作品集
    private let titleMock = ["全裸監督", "ストレンジャー・シングス", "愛の不時着", "梨泰院クラス"]

    // New Episodeを押したとき
    @IBAction func didTapUpdateEpisode(_ sender: Any) {
        print("New Episode Released！")

        // 今回は適当にエピソードを発行する
        let title = titleMock.randomElement() ?? "No Data"
        let episode = Int.random(in: 1..<10)
        subject.setNewData(with: title, episode: episode)
    }

    // John側のボタンを押したとき（Paulでも同様）
    @IBAction func didTapJohnRegister(_ sender: Any) {
        john = John(with: subject)
    }

    @IBAction func didTapJohnRemove(_ sender: Any) {
        guard let observer = john else {
            return
        }
        subject.remove(observer: observer)
    }
}
```

# Decoratorパターン
## 概要
既存のオブジェクトに**付加的な責務を動的に付与する**ことで機能を拡張する。
単純な継承を行うよりも比較的柔軟な機能拡張を行える。

`Decoratoration（装飾する）`からも想像できるように、オブジェクトの機能を総称していくパターンのようですね。


## 試しに作ったもの
ラーメンをベースに、トッピングを選んで会計をする画面を作りました。

ベースのラーメンが600円、煮卵80円、海苔50円、チャーシュー100円で作っています。

|<img width="200" alt="DecoratorSampleApp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/e85a7e7d-3d4a-82d1-78ee-59951f9b2f11.png">|
|:--|

画像のように、煮卵、チャーシューを選択すると、600+80+100の780円になります。
会計ボタンを押した結果が以下です。
<img width="400" alt="DecoratePrint.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/62ae7627-7868-37c5-abd2-b0279f36cb26.png">

## クラス図
`Menu`が俗に`Component`と呼ばれるベースとなるクラスになる。
Menuの具象クラスとして`Ramen`クラスがある。

`Decorator`がラーメンの**装飾**をするためのトッピングを用意するクラスで、`SeasonedEgg（煮卵）`、`Seaweed（海苔）`、`RoasePork（チャーシュー）`を今回用意しています。
これらのクラスがMenuの状態を拡張することで品目や料金を更新することができます。

DecoratorはMenu（Component）と一緒にオブジェクトを構成するということで、ラーメンとトッピングの**型を一致させる**という従来の継承の使い方をして、かつ同じ**振る舞い**を取得するようにしています。（コンポジション/集約）
これにより、ラーメンとトッピングの組み合わせを柔軟に設定することができるようになります。

|<img width="700" alt="Decorator.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/670d4158-556d-0046-e5c4-45259e12e19f.png">|
|:--|


## 実装

```swift:Component周り
class Menu {
    /// 品目
    var description: String = "メニュー"

    /// 品目を取得する
    /// - Returns: String
    func getDescription() -> String {
        return description
    }

    /// 料金を取得する
    func cost() -> Int {
        fatalError("注文するものが選択されていません")
    }
}

class Ramen: Menu {
    override init() {
        super.init()
        
        description = "ラーメン"
    }

    // ラーメン代600円
    override func cost() -> Int {
        return 600
    }
}
```

```swift:Decorator周り
class Decorator: Menu {
    /// メニュー
    var menu: Menu

    init(_ menu: Menu) {
        self.menu = menu
    }
}

/// 煮卵（海苔、チャーシューも同様）
class SeasonedEgg: Decorator {
    override func getDescription() -> String {
        // 品目に煮卵を追加
        return menu.getDescription() + "、煮卵"
    }

    override func cost() -> Int {
        return menu.cost() + 80
    }
}
```

```swift:DecoratorViewController
class DecoratorViewController: UIViewController {
    // 省略

    // トッピングに選んだものだけ計算
    func caclulate() {
        var menu: Menu = Ramen()
        if seasonedEggSwitch.isOn {
            menu = SeasonedEgg(menu)
        }

        if seaweedSwitch.isOn {
            menu = Seaweed(menu)
        }

        if roastPorkSwitch.isOn {
            menu = RoastPork(menu)
        }
        print(menu.getDescription() + "で合計は\(menu.cost())円になります。")
    }
}
```

# Factory Methodパターン
## 概要
オブジェクト作成のためのインターフェース（Swiftの場合はプロトコル）を定義し、**サブクラスにどのクラスをインスタンス化させるかを決めさせる**。

これによって、インスタンス化させる処理をカプセル化させられる。

## 試しに作ったもの
好きなボタンを押すとそのお好み焼きを作成するような画面を作成しました。
スイッチの向きによって広島風か関西風かを選べます。

|<img width="200" alt="FactorySampleApp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/586a5b2b-e13c-5cae-58a4-f81d0308b9ec.png">|
|:--|

スイッチが右にある場合（Onの場合）、関西風〜〜お好み焼きが出来上がります。
Offにすると、広島風になります。
<img width="300" alt="FactoryePrint.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/9135e18e-88ab-e6e1-117d-30566a7d8187.png"> <img width="300" alt="FactoryePrint2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/523536f5-2184-75b7-7701-332a094732aa.png">

## クラス図
Factory Methodパターンでは**Okonomiyaki**が`Product`、**OkonomiyakiStore**が`Creator`の役割を担っている。

`Creator`がオブジェクト作成のためのメソッド（**ファクトリメソッド**）を定義し、そのサブクラスがファクトリメソッドを実装してオブジェクトを作成する。

`Product`は、Productを実装したオブジェクト（それぞれの具体的なお好み焼き）を`Creator`が呼び出すためのインターフェース（プロトコル）である。
prepare()やmix()等の処理は基本的には変わらないので、protocol extensionで実装して共通処理として扱う。

|<img width="700" alt="FactoryMethod.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/c431e450-0064-a106-484d-3aff49e45561.png">|
|:--|

## 実装

```swift:Creator周り
protocol OkonomiyakiStore {
    /// お好み焼きを作成
    func create(type: Topping) -> Okonomiyaki
}

extension OkonomiyakiStore {
    /// 注文されたお好み焼きを焼き上げる
    func order(type: Topping) -> Okonomiyaki {
        let okonomiyaki = create(type: type)

        okonomiyaki.prepare()
        okonomiyaki.mix()
        okonomiyaki.bake()

        return okonomiyaki
    }
}

/// 関西風お好み焼き専門店（広島風も同様）
class KansaiOkonimiyakiStore: OkonomiyakiStore {
    func create(type: Topping) -> Okonomiyaki {
        switch type {
        case .mix:
            return KansaiMixedOkonomiyaki()
        case .cheese:
            return KansaiCheeseOkonomiyaki()
        case .mentaiko:
            return KansaiMentaikoOkonomiyaki()
        }
    }
}
```

```swift:Priduct周り
protocol Okonomiyaki {
    /// 品目
    var name: String { get set }
}

extension Okonomiyaki {
    /// mixやbakeも同様の処理
    func prepare() {
        print("下処理")
    }

    func getName() -> String {
        return name
    }
}

/// トッピングの種類
enum Topping {
    case mix
    case cheese
    case mentaiko
}

/// ミックスお好み焼き〜関西風〜（他のお好み焼きも同様に作成する）
class KansaiMixedOkonomiyaki: Okonomiyaki {
    var name: String = "ミックスお好み焼き〜関西風〜"
}
```

```swift:FactoryViewController.swift
class FactoryViewController: UIViewController {
    /// お好み焼き店舗
    var okonomiyakiStore: OkonomiyakiStore?
    /// お好み焼きスイッチ
    @IBOutlet private weak var okonomiyakiStyleSwitch: UISwitch!

    override func viewDidLoad() {
        super.viewDidLoad()

        okonomiyakiStore = KansaiOkonimiyakiStore()
    }

    @IBAction func didSwitchOkonomiyakiStyle(_ sender: Any) {
        okonomiyakiStore = okonomiyakiStyleSwitch.isOn ? KansaiOkonimiyakiStore() : HiroshimaOkonomiyakiStore()
    }

    // チーズや明太子のボタンも同様
    @IBAction func didTapMixedButton(_ sender: Any) {
        order(with: .mix)
    }

    /// お好み焼きを注文
    func order(with topping: Topping) {
        guard let store = okonomiyakiStore else {
            return
        }
        let okonomiyaki = store.order(type: topping)
        print(okonomiyaki.getName() + "の完成です！")
    }
}
```

# Abstract Factoryパターン
## 概要
具象クラス（オブジェクト）を指定せずに一連の**関連オブジェクトや依存オブジェクトを作成する**ためのインターフェースを提供する。

クライアントが実際に作成される**具体的な製品を知ることなく**一連の製品を作成できる。

※作ったものは、Factory Methodパターンと同じものです。

## クラス図
赤い部分がFactoryMethodパターンからの差分です。

`AbstractFactory`が一連の食材オブジェクト`Sauce`を作成する役割を担い、具体的な処理は具象ファクトリで実装して食材を獲得します。
お好み焼きを作る際、FactoryMethodパターンでは地域別にクラスを作成していました。
AbstractFactoryパターンでは食材の種類が異なり、作り方は共通なものとして実装するようなパターンにします。

|<img width="800" alt="AbstractFactory.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/9e1ebc44-a5f1-5de0-d6e7-362b86043808.png">|
|:--|

## 実装
`Sauce`とその実装しているクラスは定義しただけなので省略します。
他の食材を定義する場合も同様にできます。

呼び出すViewControllerも基本的には変わりません。

```swift:IngredientFactory周り
/// 食材取得用Factory
protocol OkonomiyakiIngredientFactory: AnyObject {
    /// お好みソースを取得
    func getSauce() -> Sauce

    // 他の食材を取得したい場合は別途定義
}

/// 関西風お好み焼き食材Factory（広島風も同様）
final class KansaiOkonomiyakiIngredientFactory: OkonomiyakiIngredientFactory {
    func getSauce() -> Sauce {
        return KansaiSauce()
    }

    /*
     他の食材も同様に実装
     */
}
```
```swift:Creator周り
// protocolは基本的に変わりません

/// 関西風お好み焼き専門店（広島風も同様）
class KansaiOkonimiyakiStore: OkonomiyakiStore {
    private let factory = KansaiOkonomiyakiIngredientFactory()

    func create(type: Topping) -> Okonomiyaki {
        var okonomiyaki: Okonomiyaki
        switch type {
        case .mix:
            okonomiyaki = MixedOkonomiyaki(factory: factory)
        case .cheese:
            okonomiyaki = CheeseOkonomiyaki(factory: factory)
        case .mentaiko:
            okonomiyaki = MentaikoOkonomiyaki(factory: factory)
        }

        okonomiyaki.name += "〜関西風〜"

        return okonomiyaki
    }
}
```

```swift:Product周り
/// お好み焼き
protocol Okonomiyaki {
    /// 品目
    var name: String { get set }

    // 以下、Abstract Factory用
    /// ソース
    var sauce: Sauce? { get set }
    /// 食材を取得する
    func getFoodstuff()
}

extension Okonomiyaki {
    // 省略
}

// 他のお好み焼きも同様
class MixedOkonomiyaki: Okonomiyaki2 {
    var name: String = "ミックスお好み焼き"
    var sauce: Sauce?
    private var factory: OkonomiyakiIngredientFactory

    init(factory: OkonomiyakiIngredientFactory) {
        self.factory = factory
    }

    func getFoodstuff() {
        sauce = factory.getSauce()
    }
}
```

# Singletonパターン
## 概要
クラスが**インスタンスを一つしか持たない**ことを保証し、そのインスタンスに対するグローバルポイントを提供する。

インスタンスを複数作ると値の不整合が起きてしまう場合があるので、一貫して共通のインスタンスのデータを扱いたい時に使うのが良さそうです。

Swiftでの開発では`UIApplication.shared.hogehoge`のような使われ方をしている部分を見ることもあるかと思いますが、これはシングルトンを活用しているようです。

## 試しに作ったもの
貯金箱をシェアするような画面をそれぞれ作りました。
俺でも私でもボタンを押せば500円貯金をして、ちゃんとデータが引き継がれて値が更新されるようになっています。

|俺視点貯金|私視点貯金|
|---|---|
|<img width="200" alt="Singleton.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/e06d1994-1b5d-1976-a6db-638b32815750.png">|<img width="200" alt="Singleton2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/a1696286-0c3a-b50c-59bb-e1ef455b291b.png">|

画面を跨いでも値が取れていますね。
<img width="400" alt="SingletonPrint.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/44777801-6e20-30c4-c203-901964207869.png">

## クラス図
これまでで一番シンプルな図になりました。
それぞれの画面からシングルトンである`PiggyBank`を参照するような形です。

|<img width="500" alt="Singleton.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550560/2108d336-9899-e9f0-cf69-8e403e3feefe.png">|
|:--|

## 実装
```swift:PiggyBank.swift
class PiggyBank {
    static let shared = PiggyBank()
    private var price = 0

    private init() {}

    func updatePrice() {
        self.price += 500
    }

    func getPrice() -> Int {
        return price
    }
}
```

```swift:SingletonViewController.swift
class SingletonViewController: UIViewController {
    private let bank = PiggyBank.shared

    @IBAction private func didTapSavingButton(_ sender: Any) {
        bank.updatePrice()
        print("俺の貯金箱からの貯金で、累計：\(bank.getPrice())円になりました。")
    }
}

// 同様にSingleton2ViewControllerも実装
```
# おさらい

| パターン | 特徴 |
|:-----------|:-----------|
| Strategy | 振る舞い（アルゴリズム）をクラスに分けてカプセル化し、柔軟に切り替えられるようにする |
| Observer | オブジェクトの状態を監視し、状態が変わったらそれを監視している全てのオブジェクトに通知が飛んで更新される |
| Decorator | 既存クラスを継承せずに、拡張する形で付加的な機能を定義していく |
| Factory Method | オブジェクト作成を抽象化する。オブジェクト作成のためのインターフェース（プロトコル）を定義し、実際にどのクラスをインスタンス化するかを決めるのはサブクラスが行う |
| Abstract Factory | 関連するオブジェクト群をまとめて生成する手順を抽象化する。これによりクライアントがインスタンスの情報を知る必要なオブジェクトを作成できる　|
| Singleton    | クラスがインスタンスを一つしか持たないことを保証し、グローバルなアクセスポイントを提供する |

今回は6つのデザインパターンについて学びました。
実際に作ったアプリ（クラス図画像付き）の[GitHubのリポジトリ](https://github.com/ta9yamakawa/DesignPatterns)を共有しますので、具体的な実装をみたい方がいらっしゃったらご覧ください。

(`2021/08/19更新` [追加で勉強した分](https://qiita.com/ta9yamakawa/items/a3e72372df7b2922315b)ができたので、[リポジトリ](https://github.com/ta9yamakawa/DesignPatterns)内のディレクトリの階層を変更しました。この記事の実装は全て`Patterns1`にあります。)

参考にした書籍はまだ折り返していないかな？ってくらいなので引き続きアウトプットしていきます。

まだどういう特性があるのかをとりあえず知れたって感じなので、具体的に使う場面があるならどういうとこかはこれから考えていきたいです。

クラス図や実装は急ピッチで作った部分もあるので、アドバイスやご指摘があればコメント欄にお願いいたします。
お手柔らかにお願いいたします🥺

# 参照
**共通**
[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)

**Strategyパターン**
[Swiftで学ぶデザインパターン11 (Strategyパターン) - しめ鯖日記](https://llcc.hatenablog.com/entry/2015/07/15/235819)

**Observerパターン**

1. [【Swift】Observerパターン入門 | 2速で歩くヒト](https://www.2nd-walker.com/2020/01/16/design-pattern-observer-swift/)
1. [RxSwift をやる前にちゃんと Observer パターンを学ぶ](https://starhoshi.hatenablog.com/entry/2017/01/13/RXSwift_%E3%82%92%E3%82%84%E3%82%8B%E5%89%8D%E3%81%AB%E3%81%A1%E3%82%83%E3%82%93%E3%81%A8_Observer_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%82%92%E5%AD%A6%E3%81%B6)

**Decoratorパターン**

1. [Swiftで学ぶデザインパターン2 (Decorator パターン) - しめ鯖日記](https://llcc.hatenablog.com/entry/2015/05/30/234441)
1. [[iOS 8] Swiftでデザインパターン No.7 Decorator
](https://dev.classmethod.jp/articles/ios8-swift-design-pattern-decorator/)

**Factory Method & Abstract Factoryパターン**
[Abstract Factory パターン - デザインパターン入門 - IT専科](https://www.itsenka.com/contents/development/designpattern/abstract_factory.html)

**Singletonパターン**
[Swift におけるシングルトン・staticメソッドとの付き合い方](https://medium.com/swift-column/singleton-398078bcc58d)