[iOS 8] Swiftでデザインパターン No.5 Template Method

Template Method

Template Method とは

英単語 Template には以下のような意味があります。

  • 枠組
  • ひな型

Template Method パターンは、ある処理のおおまかなアルゴリズムをあらかじめ決めておき、そのアルゴリズムの具体的な設計をサブクラスに任せるというパターンです。

クラス図

templateMethod

ポイント

  • スーパークラスの templateMethod() で、処理の流れを定義する
  • サブクラスで、細かい部分を実装する

サンプルコード

AbstractClass

class AbstractClass {
    func templateMethod() {
        method1()
        method2()
    }
    func method1() {
        fatalError("must be overridden")
    }
    func method2() {
        fatalError("must be overridden")
    }
}

templateMethod() の流れは、method1() -> method2() の順と定義する。

ConcreteClass

class ConcreteClass: AbstractClass {
    override func method1() {
        // do something.
    }
    override func method2() {
        // do something.
    }
}

細かい処理はサブクラスで実装する。

サンプルケース

あまりにもシンプルだったため、いまいち活用方法がわかりにくいと思うので、ここで例を挙げそれを実装することにします。

例:休日の過ごし方

  • Aさんは規則正しい人
  • Bさんはだらしない人

これらを Template Method で表現します。

HolidayLife(AbstractClass に対応する)

class HolidayLife {
    func haveaGoodDay() {   // templateMethod() に対応する
        eat()
        sleep()
    }
    func eat() {    // method1() に対応する
        fatalError("must be overridden")
    }
    func sleep() {  // method2() に対応する
        fatalError("must be overridden")
    }
}

ALife(ConcreteClass に対応する)

class ALife: HolidayLife {
    override func eat() {
        println("腹8分目まで食べる")
    }
    override func sleep() {
        println("6時間だけ寝る")
    }
}

BLife(ConcreteClass に対応する)

class BLife: HolidayLife {
    override func eat() {
        println("吐くまで食べる")
    }
    override func sleep() {
        println("起きるまで寝る")
    }
}

実行

println("### Aさんの休日の過ごし方 ###")
ALife().haveaGoodDay()

println("### Bさんの休日の過ごし方 ###")
BLife().haveaGoodDay()

実行結果

### Aさんの休日の過ごし方 ###
腹8分目まで食べる
6時間だけ寝る

### Bさんの休日の過ごし方 ###
吐くまで食べる
起きるまで寝る

どうでしょうか?
AさんもBさんも、休日の過ごし方としては「食べてから寝る」という流れでしたが、その内容は全然違うものになりましたね。
このようにアルゴリズムの構造を変えずに、アルゴリズムの中にある処理をサブクラスで再定義するというのが Template Method パターンです。

まとめ

回数を重ねるにつれて、Swift に関する新たな発見がなくなってきました。
こじつけで何かを挙げるとすれば以下となります。

  • private なメソッド呼び出しの時は self を付けても付けなくてもよい