#Visitor
目次
訪問者に全ての要素に対するインターフェースを用意しておき、その要素に関する処理を訪問者にやってもらうというパターンだと理解しています
##目的
あるオブジェクト構造上の要素で実行されるオペレーションを表現する。Visitor パターンにより、オペレーションを加えるオブジェクトのクラスに変更を加えずに、新しいオペレーションを定義することができるようになる
##構成要素
・Visitor 訪問者抽象クラス
・ConcreteVisitor 訪問者具象クラス
・Element 訪問者に処理を移譲する要素の抽象クラス
・ConcreteElement 訪問者に処理を移譲する要素の具象クラス
・ObjectStructure 要素を列挙することができるクラス(らしいんですが必要性を理解できていません)
##実装
用意された材料を使って料理を作るプログラムを実装します。
###Visitor 訪問者抽象クラス
package visitor
interface Visitor {
fun visit(e: PotatoElement)
fun visit(e: CarrotElement)
fun visit(e: PorkElement)
fun visit(e: OtherElement)
fun serve()
}
###ConcreteVisitor 訪問者具象クラス
カレーを作る訪問者
package visitor
class CurryVisitor: Visitor {
private var cookingPotato = false
private var cookingCarrot = false
private var cookingPork = false
private var cookingOther = false
override fun visit(e: PotatoElement) {
cookingPotato = true
println("${e.name()}の皮を剥いて切って鍋で煮込みます。")
}
override fun visit(e: CarrotElement) {
cookingCarrot = true
println("${e.name()}の芽をとって皮を剥いて切って鍋で煮込みます。")
}
override fun visit(e: PorkElement) {
cookingPork = true
println("${e.name()}を切って鍋で煮込みます。")
}
override fun visit(e: OtherElement) {
cookingOther = true
println("カレーのルーと${e.name()}を鍋に入れて煮込みます。")
}
override fun serve() {
if (cookingPotato && cookingCarrot && cookingOther && cookingPork) {
println("カレーの完成!")
} else {
println("まだ料理中です。")
}
}
}
###Element 訪問者に処理を移譲する要素の抽象クラス
材料抽象クラス
package visitor
interface Element {
fun name(): String
fun cooking(v: Visitor)
}
###ConcreteElement 訪問者に処理を移譲する要素の具象クラス
材料具象クラスたち
じゃがいも
package visitor
class PotatoElement: Element {
override fun name(): String {
return "じゃがいも"
}
override fun cooking(v: Visitor) {
v.visit(this)
}
}
にんじん
package visitor
class CarrotElement: Element {
override fun name(): String {
return "にんじん"
}
override fun cooking(v: Visitor) {
v.visit(this)
}
}
豚肉
package visitor
class PorkElement: Element {
override fun name(): String {
return "豚肉"
}
override fun cooking(v: Visitor) {
v.visit(this)
}
}
その他
package visitor
class OtherElement: Element {
override fun name(): String {
return "塩と胡椒"
}
override fun cooking(v: Visitor) {
v.visit(this)
}
}
###使う人
package visitor
class Client {
init {
serveCurry()
}
private fun serveCurry() {
val pot = PotatoElement()
val c = CarrotElement()
val por = PorkElement()
val o = OtherElement()
val v = CurryVisitor()
pot.cooking(v)
c.cooking(v)
por.cooking(v)
v.serve()
o.cooking(v)
v.serve()
}
}
[out-put]
じゃがいもの皮を剥いて切って鍋で煮込みます。
にんじんの芽をとって皮を剥いて切って鍋で煮込みます。
豚肉を切って鍋で煮込みます。
まだ料理中です。
カレーのルーと塩と胡椒を鍋に入れて煮込みます。
カレーの完成!
野菜炒めを作りたくなったのでFriedVegetablesVisitorを実装します。
package visitor
class FriedVegetablesVisitor: Visitor {
private var cookingPotato = false
private var cookingCarrot = false
private var cookingPork = false
private var cookingOther = false
override fun visit(e: PotatoElement) {
cookingPotato = true
println("${e.name()}の皮を剥いて切って炒めます。")
}
override fun visit(e: CarrotElement) {
cookingCarrot = true
println("${e.name()}の芽をとって皮を剥いて切って炒めます。")
}
override fun visit(e: PorkElement) {
cookingPork = true
println("${e.name()}を切って炒めます。")
}
override fun visit(e: OtherElement) {
cookingOther = true
println("${e.name()}を鍋に入れて炒めます。")
}
override fun serve() {
if (cookingPotato && cookingCarrot && cookingOther && cookingPork) {
println("野菜炒めの完成!")
} else {
println("まだ料理中です。")
}
}
}
package visitor
class Client {
init {
serveCurry()
println("--------------------------------")
serveFriedVegetables()
}
private fun serveFriedVegetables() {
val pot = PotatoElement()
val c = CarrotElement()
val por = PorkElement()
val o = OtherElement()
val v = FriedVegetablesVisitor()
pot.cooking(v)
c.cooking(v)
por.cooking(v)
v.serve()
o.cooking(v)
v.serve()
}
private fun serveCurry() {
val pot = PotatoElement()
val c = CarrotElement()
val por = PorkElement()
val o = OtherElement()
val v = CurryVisitor()
pot.cooking(v)
c.cooking(v)
por.cooking(v)
v.serve()
o.cooking(v)
v.serve()
}
}
###出力結果
[out-put]
じゃがいもの皮を剥いて切って鍋で煮込みます。
にんじんの芽をとって皮を剥いて切って鍋で煮込みます。
豚肉を切って鍋で煮込みます。
まだ料理中です。
カレーのルーと塩と胡椒を鍋に入れて煮込みます。
カレーの完成!
--------------------------------
じゃがいもの皮を剥いて切って炒めます。
にんじんの芽をとって皮を剥いて切って炒めます。
豚肉を切って炒めます。
まだ料理中です。
塩と胡椒を鍋に入れて炒めます。
野菜炒めの完成!