#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
かなり基本的なパターンですね。あらゆるところで使用するかと思います。
以上