Help us understand the problem. What is going on with this article?

Swiftを使用してデザインパターンまとめ 3.Template Methodパターン

More than 1 year has passed since last update.

はじめに

この投稿は 増補改訂版 Java言語で学ぶデザインパターン入門 に沿って学んだことを章ごとにまとめるものです.
今回は第3章 Template Method についてまとめます.

Template Method とは

Template Methodってどんなパターン?

  • スーパークラス側で抽象メソッドを定義
  • スーパークラス内で抽象メソッドの呼び出し方を定義 <- ここが「テンプレート」に相当します
  • サブクラスごとに抽象メソッドを定義

何が嬉しいの?

  • 大まかな処理の流れを共通化できる
  • 処理の中身は違う,流れは共通な処理を呼び出せる
  • 大まかの処理の流れの順番等に変更が生じた場合,簡単に修正できる

注意すること

  • メソッドの呼び出され方はスーパークラスに実装されているのでスーパークラスの実装を意識する必要がある
  • サブクラスが量産されたりするので, Template Method パターンにこだわりすぎないように注意

実装例

目的

今回は顔文字を出力するためのクラスを作成します.

今回はスーパークラスとして Protocol を使用しました.

実装

Emoticon プロトコル

顔文字を出力するために必要なメソッドやプロパティを定義したプロトコル

Emoticon
protocol Emoticon {
    /// 顔の文字列 (例: "^o^")
    var face: String { get }
    /// 顔の文字列で初期化
    init(face: String)
    /// 顔の左側の文字列 (例: "\(")
    func makeLeftSide() -> String
    /// 顔の右側の文字列 (例: ")/")
    func makeRightSide() -> String
    /// 顔文字の表示 (上記の例では "\(^o^)/" が表示される)
    func printEmoticon()
}
extension Emoticon {
    /// 顔文字の表示メソッドの実装
    func printEmoticon() {
        // プロトコルで定義されたまだ中身のないメソッドを使用して顔文字を作る
        // ここがテンプレート部分にあたる
        let emoticon = makeLeftSide() + face + makeRightSide()
        print(emoticon)
    }
}

Normal クラス

基本的な () で囲まれた顔文字用のクラスです.

Normal
final class Normal: Emoticon {
    let face: String
    required init(face: String) {
        self.face = face
    }
    func makeLeftSide() -> String {
        return "("
    }
    func makeRightSide() -> String {
        return ")"
    }
}

Crab クラス

v()v で顔を囲まれた顔文字用のクラスです.
かにクラスってなんかテンション上がりません?(?)v(`・ω・´)vかに
実装は Normal クラスと同じです.

Crab
final class Crab: Emoticon {
    let face: String
    required init(face: String) {
        self.face = face
    }
    func makeLeftSide() -> String {
        return "v("
    }
    func makeRightSide() -> String {
        return ")v"
    }
}

動作確認

実装は以上です.
実際に Normal クラスと,かにクラスにシャキーンの顔を渡してみます.

Normal(face: "`・ω・´").printEmoticon() // (`・ω・´)
Crab(face: "`・ω・´").printEmoticon()   // v(`・ω・´)v

このように,同じ printEmoticon() メソッドを呼んでおり,スーパークラス(今回はプロトコル)の中身も同じですが, makeLeftSide()makeRightSide() の実装が異なるため,違う内容が出力されました.

まとめ

今回は Template Method パターンをまとめました.

Template Method の形

AbstractClass (抽象クラス) 役

今回は Emoticon プロトコルがこの役をしました.
サブクラスで定義する抽象メソッドの呼び出し方や大まかな流れをここで定義しました.

ConcreteClass (具象クラス) 役

今回は Normal クラスと,かにクラスにあたります.
それぞれの Emoticon プロトコルに呼び出されるメソッドを実装しました.

クラス図

TemplateMethod.png

思ったこと

  • 基本の基本,という感じの考え方だと思います,自然に使っていきたい.
  • 継承の形を使用するので, templateMethod 内でのみ使用したいメソッドを抽象メソッドとして定義するべきではなさそう. (そういう意味では今回の実装例はあまりよろしくない)
    • 単体でも使う想定のメソッドを抽象メソッドとして定義するべき (クラスの外から呼び出すことができてしまうため)
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away