Kotlin Design Pattern: Visitor

The visitor pattern is used to separate a relatively complex set of structured data classes from the functionality that may be performed upon the data that they hold.

Setup

  • Visitor:
    Declare a Visite operation for each class of ConcreteElement in the object structure. The operation's name and signature identifies the class that sends the Visit request to the visitor. That lets the visitor determine the concrete class of the element being visited. Then the visitor can access the element directly through particular interface.
  • Concrete Visitor
    Implement each operation declared by Visitor. Each operation implements a fragment of the algorithm defined for the corresponding class of object in the structure. ConcreteVisitor provides the context for the algorithm and stores the local state. This states often accumulates results during the traversal of the structure.
  • Element
    Define an accept operation which takes a visitor as argument.
  • Concrete Element
    Implement the operation that takes a visitor as argument.
  • Client

Example 1

// Step 5: Client code

fun main(args: Array<String>) {
    val oneVisitor = OneVisitor()
    val sightSeeing = SightSeeing()

    sightSeeing.accept(oneVisitor)
}

// Step 1: Visitable Interface (Element interface)

interface Visitable{
    fun accept(visitor: Visitor)
}

// Step 2: Concrete Visitable (Concrete Element)

class Palace: Visitable{
    override fun accept(visitor: Visitor) {
        visitor.visit(this)
    }
}

class Museum: Visitable{
    override fun accept(visitor: Visitor) {
        visitor.visit(this)
    }
}

class Monument: Visitable{
    override fun accept(visitor: Visitor) {
        visitor.visit(this)
    }
}

class SightSeeing: Visitable{
    private val visitable = arrayOf(Palace(), Museum(), Monument())
    override fun accept(visitor: Visitor) {
        for (v in visitable)
            v.accept(visitor)
    }
}

// Step 3: Visitor Interface

interface Visitor{
    fun visit(visitable: Visitable)
    fun visit(visitable: Palace)
    fun visit(visitable: Museum)
    fun visit(visitable: Monument)
}

// Step 4: Concrete Visitor

class OneVisitor: Visitor{
    override fun visit(visitable: Visitable) {
        println("I am visiting ${visitable.javaClass.simpleName}")
    }

    override fun visit(visitable: Monument) {
        println("I am visiting ${visitable.javaClass.simpleName}")
    }

    override fun visit(visitable: Museum) {
        println("I am visiting ${visitable.javaClass.simpleName}")
    }

    override fun visit(visitable: Palace) {
        println("I am visiting ${visitable.javaClass.simpleName}")
    }
}

/**
        prints

        I am visiting Palace
        I am visiting Museum
        I am visiting Monument
        
 **/

Example 2

// Step 5: Client code

fun main(args: Array<String>) {
    val customer = OneCustomer()

    val shopList = arrayOf(Toothpaste(2), Tissues(6), Lotion(1))

    shopList.forEach { it.accept(customer) }

    println("Sum = ${customer.sum}")
}

// Step 1: Visitable Interface

interface Commodity{
    fun accept(visitor: Customer)
}

// Step 2: Concrete Visitable

class Toothpaste(private val quantity: Int): Commodity{
    override fun accept(visitor: Customer) {
        println("Article: ${this.javaClass.simpleName}, Quantity: $quantity")
        visitor.visit(visitable = this, quantity = quantity)
    }
}

class Tissues(private val quantity: Int): Commodity{
    override fun accept(visitor: Customer) {
        println("Article: ${this.javaClass.simpleName}, Quantity: $quantity")
        visitor.visit(visitable = this, quantity = quantity)
    }
}

class Lotion(private val quantity: Int): Commodity{
    override fun accept(visitor: Customer) {
        println("Article: ${this.javaClass.simpleName}, Quantity: $quantity")
        visitor.visit(visitable = this, quantity = quantity)
    }
}

// Step 3: Visitor Interface

interface Customer{
    fun visit(visitable: Toothpaste, quantity: Int)
    fun visit(visitable: Tissues, quantity: Int)
    fun visit(visitable: Lotion, quantity: Int)
}

// Step 4: Concrete Visitor

class OneCustomer: Customer{
    var sum: Int = 0

    override fun visit(visitable: Lotion, quantity: Int) {
        sum += quantity * 30
    }

    override fun visit(visitable: Tissues, quantity: Int) {
        sum += quantity * 10
    }

    override fun visit(visitable: Toothpaste, quantity: Int) {
        sum += quantity * 15
    }
}

/**
        prints

        Article: Toothpaste, Quantity: 2
        Article: Tissues, Quantity: 6
        Article: Lotion, Quantity: 1
        Sum = 120

 **/
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 今天跟gay蜜微信聊天时我在问他为什么要发文说“对不起,同性恋不上瘾”,因为我是不同意他观点的。在我看来,我们每个...
    叁肆伍阅读 1,549评论 27 25
  • 之前报了研发本部的设计质量部,今天晚上去面试了,一共要俩人,也一共有俩人面试,所以成功率是100%吧,哈哈。 不过...
    青青子衿_5457阅读 138评论 0 0
  • 如果我渡过了深邃的海洋 如果我翻越了高耸的山川 如果我穿梭人山人海只为相遇 如果我愿不顾一切追寻你的踪迹 如果我再...
    万一lxq阅读 250评论 0 4