Blog Infos
Author
Published
Topics
, , , ,
Published
Purpose of the pattern

Separation of an algorithm from the object structure. Think of a Visitor as someone who visits multiple places and does something different depending on the place. This means we need to modify Visitor instead of the place itself.

It’s mostly used to implement new things that don’t make sense inside an object but are required for the new feature to work.

What do we get from that?
  • Open/Closed: we can add new algorithms without changing the object structure.
  • Single Responsibility: each class is responsible for a different behavior.
  • Extension of a class with little to no modification to it.
  • Avoidance of polluting the object class.

The biggest downside is that you must update all Visitors when a class is added or removed from the hierarchy.

Implementation

In the diagram, we have our Visitor that has methods for visiting concrete implementations of Element , therefore it’s dependent on each Element implementation.

At the same time, Element is dependent on a Visitor interface. We’re doing this to avoid checking the type of Element each time we want to use Visitor instead, we’ll accept Visitor and use the right method inside Element . The method will be a 1-liner that calls the right Visitor method.

Moreover, we’re able to create multiple ConcreteVisitors that can do different things.

Example

Your task is to add an Export to CSV feature to a body health system. Your manager is also thinking about adding other export options. Adding function to the Body would look at least strange it should be separated.

It’s a perfect use case for Visitor because we can add new export options easily without interfering with much of the body health system. Here’s how we’ll structure our code:

Body Health Export system

Job Offers

Job Offers


    Senior Android Developer

    SumUp
    Berlin
    • Full Time
    apply now

    Senior Android Engineer

    Carly Solutions GmbH
    Munich
    • Full Time
    apply now

OUR VIDEO RECOMMENDATION

No results found.

Jobs

In real app BodyPart would also have other functions, but we want to keep things simple in the example. Let’s start by coding BodyParts along with Visitor interface:

interface Visitor {
    fun visitEye(eye: Eye)
    fun visitMouth(mouth: Mouth)
}

interface BodyPart {
    fun accept(visitor: Visitor)
}

class Eye(val color: String) : BodyPart {
    override fun accept(visitor: Visitor) {
        visitor.visitEye(this)
    }
}

class Mouth(val size: Int) : BodyPart {
    override fun accept(visitor: Visitor) {
        visitor.visitMouth(this)
    }
}

Now, Visitor implementations have access to Mouth and Eye . Let’s start coding ExportToCSVVisitor :

class ExportToCSVVisitor : Visitor {
    override fun visitEye(eye: Eye) {
        println("csv eye: ${eye.color}")
    }

    override fun visitMouth(mouth: Mouth) {
        println("csv mouth: ${mouth.size}")
    }
}

Again, for simplicity Eye and Mouth have 1 parameter and we’ll just print the info.

Here’s how to use it:

fun main() {
    val visitor: Visitor = ExportToCSVVisitor()
    val bodyParts = listOf(
        Eye("blue"),
        Eye("borwn"),
        Mouth(20),
    )
    bodyParts.forEach { it.accept(visitor) }
    // csv eye: blue
    // csv eye: borwn
    // csv mouth: 20
}

There is no need to know the type of BodyPart when using Visitor methods because all of them have accept function that chooses the right Visitor function.

Thanks for reading! Please clap if you learned something, and follow me for more!

Learn more about design patterns:

https://medium.com/@michalankiersztajn/list/design-patterns-in-kotlin-12e52466affe?source=post_page—–21f474309210——————————–

Based on the book:

“Wzorce projektowe : elementy oprogramowania obiektowego wielokrotnego użytku” — Erich Gamma Autor; Janusz Jabłonowski (Translator); Grady Booch (Introduction author); Richard Helm (Author); Ralph Johnson (Author); John M Vlissides (Author)

This article is previously published on proandroiddev.com

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
Hi, today I come to you with a quick tip on how to update…
READ MORE
blog
Automation is a key point of Software Testing once it make possible to reproduce…
READ MORE
blog
Drag and Drop reordering in Recyclerview can be achieved with ItemTouchHelper (checkout implementation reference).…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu