[Swift]"デリゲートデザインパターン"ってなに？

**デリゲートデザインパターン**ってなんだ・・・？

>参考・引用　[「親切すぎるiPhoneアプリ開発」](http://www.shuwasystem.co.jp/products/7980html/4320.html)

##デリゲート（delegate）とは

>簡単に言うとあるクラスから処理の一部を他のクラスに任せたり、他のクラスへメッセージを送る等の目的でよく使われるデザインパターンです。 

>[参考：ぬけてるエンジニアの備忘録](http://nukenuke.hatenablog.com/entry/2015/09/17/120749)


##どんな時に使うの？

>デリゲートを実装する時に考えることは何を委譲するか(なんの処理を呼ばせるのか)を決めるだけです。ぶっちゃけ誰に委譲するか(どこから呼ぶのか)は考えなくて良いです。 

>[参考：ぬけてるエンジニアの備忘録](http://nukenuke.hatenablog.com/entry/2015/09/17/120749)

処理としては毎回行なうけれども、時と場合によっては処理内容は変えていきたい、
という場合に使うようです。

##どんな仕組み？

例えば、ある主人公が以下のような生活をしていたとします。

| 平日の行動 | いつもの場合 |
|:---------:|------------|
| 登校      |自転車で登校|
| 昼食      |友達と昼食|
| 放課後    |家に戻る|

ところが、彼女ができた主人公は日常の行動に影響を受けるわけです。

| 平日の行動 | 彼女なし  |彼女あり|
|:---------:|----------|------|
| 登校      |自転車で登校|彼女に合わせる|
| 昼食      |友達と昼食 |彼女に合わせる|
| 放課後    |家に戻る   |彼女に合わせる|

平日のルーティーンに変化はありませんが、彼女に合わせて内容を変えるので毎回変わってしまうのです。
ですが、主人公が 登校・昼食・放課後 を過ごし方をしているのは確かです。

<img width="484" alt="スクリーンショット 2016-01-14 08.54.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/103475/bf0b3d3a-5dcc-3676-9402-3d9dd5489e39.png">

このように、行動を相手に任せることを移譲（delegate:デリゲート）と言います。

##どうやって使うの？

このデリゲートデザインパターンを実現する際にはプロトコルの利用が考えられます。

```swift:02/Study-22.playground
protocol ScheduleDelegate {
    func gotoSchool()    //登校どうする？
    func lunchTime()     //昼食どうする？
    func afterSchool()   //放課後どうする？
}
```

プロトコルに規定することで、この「ScheduleDelegate」プロトコルを採用しているクラスには上記のメソッドが実装されていることが保証されます。

主人公には、このScheduleDelegateを採用したオブジェクトをプロパティとして持たせます。
ただし、最初の主人公には彼女がいませんのでそのように表現しないといけません。

```swift
protocol ScheduleDelegate {
    func gotoSchool()    //登校どうする？
    func lunchTime()     //昼食どうする？
    func afterSchool()   //放課後どうする？
}

class Hero {
    var girlFriend:ScheduleDelegate? = nil
・・・
}
・・・
var hero = Hero(・・・)
```

彼女がいれば、処理をデリゲートします。
いなければ、デリゲートしません。

```swift:
protocol ScheduleDelegate {
    func gotoSchool()    //登校どうする？
    func lunchTime()     //昼食どうする？
    func afterSchool()   //放課後どうする？
}

class Hero : Person {
    var girlFriend:ScheduleDelegate? = nil   //彼女（移譲先）がいないよ
    func oneday() {
        if let gf = self.girlFriend {     //彼女いますか？
            gf.gotoSchool()
            gf.lunchTime()
            gf.afterSchool()
        } else {
            print("一人で自転車で学校に行く")
            print("お弁当はコンビニ弁当")
            print("帰りはビデオ屋に行く")
        }
    }
}
```

girlFriendプロパティに代入するオブジェクトは、ScheduleDelegateプロトコルを採用していれば何でもOKです。

```swift:
class GirlFriend : ScheduleDelegate {
  ・・・
}
```

girlをheroのgirlFriendプロパティに設定する前と後で、onedayメッセージを送ったときの動作が変わります。

```swift:
・・・
print("＊彼女ができる前の生活")
hero.oneday()
・・・
hero.girlFriend = girl    //girl を彼女（移譲先）に設定します
・・・
print("＊彼女ができた後の生活")
hero.oneday()
・・・
```

こちらのサンプルコードをplaygroundファイルで作成し、実行してみてください。

```swift:Sample.playground
protocol ScheduleDelegate {
    func gotoSchool()    //登校どうする？
    func lunchTime()     //昼食どうする？
    func afterSchool()   //放課後どうする？
}

class Hero {
    var girlFriend:ScheduleDelegate? = nil
    func oneday() {
        if let gf = self.girlFriend {
            gf.gotoSchool()
            gf.lunchTime()
            gf.afterSchool()
        } else {
            print("一人で自転車で学校に行く")
            print("お弁当はコンビニ弁当")
            print("帰りはビデオ屋に行く")
        }
    }
}

class GirlFriend : ScheduleDelegate {
    func gotoSchool() {
        print("電車で学校に行く")
    }
    func lunchTime() {
        print("お弁当は海老フライ")
    }
    func afterSchool() {
        print("帰りは映画に行く")
    }
}

var hero = Hero()
var girl = GirlFriend()

print("＊彼女ができる前の生活")
hero.oneday()
hero.girlFriend = girl
print("")
print("＊彼女ができた後の生活")
hero.oneday()
```

実行結果はこうなれば成功です。

<img width="313" alt="スクリーンショット 2016-01-14 09.43.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/103475/622fc59a-4e36-63e1-ec41-c171fafa2db2.png">

以上。


>文言・コード引用元：　[「親切すぎるiPhoneアプリ開発」](http://www.shuwasystem.co.jp/products/7980html/4320.html)