考虑访问者设计模式,并表明在Kotlin上编程时不应使用它。在实践研究的支持下,将有一个理论,一个极简的实现,一个替换的实现以及支持替换的论点。将没有类图。您可以在play.kotlinlang.org上在线尝试所有内容

在我的 极端最后的工作由微服务负责,该服务将一个不良的JSON转换为不良的JSON。开发人员将有限状态机固定在那里,然后在上方放置了一个访客模板。关于State Machine并不是那么有趣,但是当我看到Visitor时,我呼气-“哇!”。这非常罕见,因为我相信这种技术很少有人能正确理解。有一个明显的错误理解现象-似乎可以理解,但是他们看不到它在直截了当的范围内的适用性,并且工作原理无法得到解决,考虑它并不舒服。它通常被编译器等的开发人员接受-这表明掌握母盘的高级水平。但是范围更广-很难识别。
广泛的理论
Visitor. . , LinkedIn , , . Visitor , ( ). Hollywood Agent — " — ". - . , . Python JavaScript . "", — — , . Java .
, , ( ) . , , ( ), . — . Kotlin " " , ( , ).
— Visitor . Visitor , , . , , , , . , , , , . Visitor.
, : . sealed class , .
: .
fun main() {
Guest().visit( Human(""))
Guest().visit( Cat(""))
}
sealed class LivingCreature
class Human(val name: String): LivingCreature()
class Cat(val colour: String): LivingCreature()
interface Visitor {
fun visit(creature : Human)
fun visit(creature : Cat)
}
class Guest: Visitor {
override fun visit(human: Human) = println(" ${human.name}")
override fun visit(pet: Cat) = println(" ( ${pet.colour})")
}
— . , visit . , Human Cat LivingCreature. :
fun main() {
val human: LivingCreature = Human("")
val cat : LivingCreature = Cat("")
Guest().visit( human)
Guest().visit( cat )
}
sealed class LivingCreature
class Human(val name: String): LivingCreature()
class Cat(val colour: String): LivingCreature()
interface Visitor {
fun visit(creature : Human)
fun visit(creature : Cat)
}
class Guest: Visitor {
override fun visit(human: Human) = println(" ${human.name}")
override fun visit(pet: Cat) = println(" ( ${pet.colour})")
}
, visit(LivingCreature). , , — , , . , , .
Visitor. , , — Human Cat, , Guest (Visitor) . LivingCreature Visitor visit, .
fun main() {
val human: LivingCreature = Human("")
val cat : LivingCreature = Cat("")
human.accept( Guest() )
cat.accept( Guest() )
}
sealed class LivingCreature {
abstract fun accept(visitor: Visitor)
}
interface Visitor {
fun visit(creature : Human)
fun visit(creature : Cat)
}
class Human(val name: String): LivingCreature() {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
class Cat(val colour: String): LivingCreature(){
override fun accept(visitor: Visitor) = visitor.visit(this)
}
class Guest : Visitor{
override fun visit(creature : Human) = println(" ${creature.name}")
override fun visit(creature : Cat) = println(" ( ${creature.colour})")
}
— inline fun , - .
— visit , — ( ) . accept, — . Visitor.
— . . — accept. , . , — . Visitor.
, Visitor — , - .
" "?
LivingCreature Visitor.visit(LivingCreature)?
fun main() {
val human: LivingCreature = Human("")
val cat : LivingCreature = Cat("")
Guest().visit(human )
Guest().visit( cat )
}
sealed class LivingCreature
interface Visitor {
fun visit(creature: LivingCreature)
}
class Human(val name: String): LivingCreature()
class Cat(val colour: String): LivingCreature()
class Guest : Visitor{
override fun visit(creature : LivingCreature) = when(creature) {
is Human -> println( " ${creature.name}")
is Cat -> println( " ( ${creature.colour} ) ")
}
}
, , . . ? , Java instanceof , , , JVM — Java. - — ++. "" . - , instanceof , JVM. , JVM .
事实证明,您可以使用JHM编写Kotlin和Java性能测试。结果让我感到惊讶-带有Visitor 的版本比使用when / smart cast的版本慢许多倍。您可以在这里看到它:我在GitHub上的存储库
发现
- 访客对于头脑来说是一种很棒的锻炼,我强烈建议您在意料之外的情况下尝试尝试,但出于学术目的。
- 访问者改进了可视Java代码,并使您可以更清楚地表达行为。对于生成器来说,事件处理程序模式是一个不错的选择(请参阅ANTLR)。
- 由于语言的特殊性,访问者对Kotlin上的“天真”解决方案失去了可读性和性能。