Visitor – Patrones de diseño

Avatar
2 min lectura

El patrón de diseño Visitor es un patrón de diseño de software que permite agregar comportamientos nuevos a una estructura de objetos sin modificar las clases de los objetos individuales.

Esto se logra mediante la creación de una clase Visitor que contiene los nuevos comportamientos y la implementación de una interfaz en cada clase de la estructura de objetos que permita la visita del visitor.

En Kotlin, podemos implementar el patrón de diseño Visitor utilizando una clase sealed y las interfaces de visita.

Por ejemplo, supongamos que tenemos una estructura de objetos que representa una factura con diferentes elementos, como productos, impuestos y descuentos.

Podemos crear una clase sealed llamada Element que represente cada uno de estos elementos y una interfaz llamada Visitor que contenga los métodos de visita para cada uno de ellos:

sealed class Element {
    abstract fun accept(visitor: Visitor)
}

interface Visitor {
    fun visit(product: Product)
    fun visit(tax: Tax)
    fun visit(discount: Discount)
}

Luego, podemos crear las clases concretas que implementen la clase sealed Element y la interfaz Visitor para cada uno de los elementos de la factura:

class Product(val name: String, val price: Double) : Element() {
    override fun accept(visitor: Visitor) {
        visitor.visit(this)
    }
}

class Tax(val rate: Double) : Element() {
    override fun accept(visitor: Visitor) {
        visitor.visit(this)
    }
}

class Discount(val amount: Double) : Element() {
    override fun accept(visitor: Visitor) {
        visitor.visit(this)
    }
}

Por último, podemos crear una clase visitor concreta que implemente la interfaz “Visitor” y contenga los comportamientos deseados para cada uno de los elementos de la factura:

class InvoiceVisitor : Visitor {
    var total = 0.0

    override fun visit(product: Product) {
        total += product.price
    }

    override fun visit(tax: Tax) {
        total *= (1 + tax.rate)
    }

    override fun visit(discount: Discount) {
        total -= discount.amount
    }
}

De esta manera, podemos utilizar la clase InvoiceVisitor para calcular el total de la factura sin tener que modificar las clases de los elementos individuales. Por ejemplo:

val elements = listOf(
    Product("Laptop", 1000.0),
    Tax(0.15),
    Discount(100.0)
)

val visitor = InvoiceVisitor()

for (element in elements) {
    element.accept(visitor)
}

println("Total: ${visitor.total}") // Total: 915.0

En este ejemplo, la clase InvoiceVisitor recorre la lista de elementos y visita cada uno de ellos, aplicando los comportamientos deseados para calcular el total de la factura.

De esta manera, podemos agregar nuevos comportamientos a la estructura de objetos de la factura sin tener que modificar las clases de los elementos individuales.

Conclusión

En resumen, el patrón de diseño Visitor es una forma de agregar nuevos comportamientos a una estructura de objetos sin modificar las clases de los objetos individuales.

Esto se logra mediante la creación de una clase visitor que contiene los nuevos comportamientos y la implementación de una interfaz en cada clase de la estructura de objetos que permita la visita del visitor.

En Kotlin, podemos utilizar una clase sealed y las interfaces de visita para implementar el patrón de diseño Visitor de manera sencilla y eficiente.