LoginSignup
0
0

【Gang of Four】Template Method

Last updated at Posted at 2019-08-21

#Template Method
目次
アルゴリズムの共通部分を抽象化して、振る舞いが異なる部分を具象クラスで実装するパターンです。説明だけ読むとStrategyパターンと同じですがあっちは委譲、こっちは継承で実現します。

継承は依存関係が強力になってしまうので個人的にはStrategyパターンのほうが優れているのではないかな?と思っています。

ただ、こちらのほうが実装するクラスが少なくて済みます。

##目的
1つのオペレーションにアルゴリズムのスケルトンを定義しておき、その中のいくつかのステップについては、サブクラスでの定義に任せることにする。Template Method パターンでは、アルゴリズムの構造を変えずに、アルゴリズム中のあるステップをサブクラスで再定義する。

##構成要素
・AbstractClass 共通部分
・ConcreteClass 共通じゃない部分

##実装
Strategyパターンと同様、配列をソートするプログラムを実装します。

###AbstractClass 共通部分

BubbleSort.kt
package templatemethod

abstract class BubbleSort {
    private var operations = 0
    protected var length = 0

    protected fun doSort(): Int {
        operations = 0
        if (length <= 1) return operations

        for (nextToLast in length - 1 downTo 0) {
            for (index in 0 until nextToLast) {
                if (outOfOrder(index)) swap(index)
                operations++
            }
        }
        return operations
    }

    protected abstract fun swap(index: Int)
    protected abstract fun outOfOrder(index: Int): Boolean
}

###ConcreteClass 共通じゃない部分
Int型配列用具象クラス

IntBubbleSort.kt
package templatemethod

class IntBubbleSort: BubbleSort() {

    private lateinit var array: Array<Int>

    fun sort(theArray: Array<Int>): Int {
        array = theArray
        length = theArray.size
        return doSort()
    }

    override fun swap(index: Int) {
        val temp = array[index]
        array[index] = array[index + 1]
        array[index + 1] = temp
    }

    override fun outOfOrder(index: Int): Boolean {
        return array[index] > array[index + 1]
    }

}

Double型配列用具象クラス

DoubleBubbleSort.kt
package templatemethod

class DoubleBubbleSort: BubbleSort() {

    private lateinit var array: Array<Double>

    fun sort(theArray: Array<Double>): Int {
        array = theArray
        length = theArray.size
        return doSort()
    }

    override fun swap(index: Int) {
        val temp = array[index]
        array[index] = array[index + 1]
        array[index + 1] = temp
    }

    override fun outOfOrder(index: Int): Boolean {
        return array[index] > array[index + 1]
    }
}

まあこれもジェネリクス使えば一つのクラスで実現できますが…

###使う人

Client.kt
package templatemethod

class Client {
    init {
        val intArray = arrayOf(332, 1, 13, 3232, 456, 22, 5)
        println("Int配列ソート前")
        intArray.forEach {
            println(it)
        }
        // 並べ替え
        IntBubbleSort().sort(intArray)
        println("Int配列ソート後")
        intArray.forEach {
            println(it)
        }

        val doubleArray = arrayOf(10.01, 10.5, 10.4123, 10.12, 10.87)
        println("Double配列ソート前")
        doubleArray.forEach {
            println(it)
        }
        // 並べ替え
        DoubleBubbleSort().sort(doubleArray)
        println("Double配列ソート後")
        doubleArray.forEach {
            println(it)
        }
    }
}

###出力結果

[out-put]
Int配列ソート前
332
1
13
3232
456
22
5
Int配列ソート後
1
5
13
22
332
456
3232
Double配列ソート前
10.01
10.5
10.4123
10.12
10.87
Double配列ソート後
10.01
10.12
10.4123
10.5
10.87

かなり基本的なパターンですね。あらゆるところで使用するかと思います。

以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0