Le modèle Visitor est déconseillé pour Kotlin, mais il vaut la peine de le savoir

Considérez le modèle de conception Visitor et montrez que vous ne devez pas l'utiliser lors de la programmation sur Kotlin. Il y aura une théorie, une mise en œuvre minimaliste, la mise en œuvre d'un remplacement et les arguments en faveur d'un remplacement, étayés par des recherches pratiques. Il n'y aura pas de diagrammes de classes. Vous pouvez tout essayer en ligne sur play.kotlinlang.org



Sur mon extrême , JSON . Finite State Machine, Visitor. 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() ) //   LivingCreature.accept( Visitor ),         
    cat.accept( Guest() ) // 
}

sealed class LivingCreature {
    abstract fun accept(visitor: Visitor) //    inline fun -     
}
interface Visitor {
    fun visit(creature : Human)
    fun visit(creature : Cat)
}
class Human(val name: String): LivingCreature() {
    override fun accept(visitor: Visitor) = visitor.visit(this) //    Human,    visit(Human)  -
}
class Cat(val colour: String): LivingCreature(){
    override fun accept(visitor: Visitor) = visitor.visit(this) //    Cat,    visit(Cat)  -
}

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 .


Il s'avère que vous pouvez écrire des tests de performances Kotlin et Java dans JHM , ce que j'ai fait. Le résultat m'a surpris - la version avec Visitor fonctionne beaucoup plus lentement que la version avec when / smart cast . Vous pouvez le voir ici:
mon référentiel sur GitHub


résultats


  • Le visiteur est un excellent exercice pour l'esprit et je recommande fortement de l'essayer dans des situations inattendues, mais par intĂ©rĂŞt acadĂ©mique.
  • Visitor amĂ©liore le code Java visuel et vous permet d'exprimer le comportement plus clairement. Une bonne option pour les gĂ©nĂ©rateurs, les modèles de gestionnaire d'Ă©vĂ©nements (voir ANTLR).
  • Le visiteur perd en lisibilitĂ© et en performance Ă  la solution «naĂŻve» sur Kotlin en raison des particularitĂ©s de la langue.

All Articles