Composite – Patrones de Diseño
Antonio Leiva

El patrón de diseño Composite es una técnica utilizada en programación orientada a objetos para tratar grupos de objetos de manera uniforme, como si fueran un solo objeto.

Este patrón permite a los desarrolladores construir estructuras jerárquicas y manejar los elementos de forma recursiva.

En Kotlin, el patrón Composite se implementa mediante la interface Composable y la clase Composite, que se utilizan para definir la estructura del grupo de objetos y sus operaciones respectivamente.

Estructura de implementación en Kotlin

// Interface que define la operación composable
interface Composable {
    fun operation(): String
}

// Clase que representa un objeto individual del grupo
class IndividualObject: Composable {
    override fun operation() = "Individual object operation"
}

// Clase que representa el grupo de objetos y sus operaciones
class Composite: Composable {
    private val objects = mutableListOf<Composable>()

    fun add(object: Composable) {
        objects.add(object)
    }

    fun remove(object: Composable) {
        objects.remove(object)
    }

    override fun operation() = objects.map { it.operation() }.joinToString(separator = "\n")
}

// Creación del grupo de objetos y su uso
fun main() {
    val composite = Composite()

    composite.add(IndividualObject())
    composite.add(IndividualObject())

    println(composite.operation()) // Imprime la operación de cada objeto del grupo
}

Ventajas del patrón Composite

  • Permite tratar a un grupo de objetos de manera uniforme, lo que facilita su manejo y organización.
  • Permite construir estructuras jerárquicas y manejarlas de manera recursiva.
  • Provee una interfaz común para todos los objetos del grupo, lo que facilita su extensión y modificación.

Desventajas del patrón Composite

  • Puede ser complejo de implementar y difícil de entender para programadores no familiarizados con el patrón.
  • Puede aumentar la complejidad del código y dificultar su depuración.

Ejemplo

Un ejemplo concreto del uso del patrón Composite puede ser el desarrollo de una aplicación de dibujo en la que se puedan crear y manipular diferentes figuras geométricas.

Por ejemplo, se puede implementar una clase abstracta Figure que represente a una figura genérica y tenga métodos para dibujarla, moverla y obtener su área. Luego, se pueden crear clases concretas como Circle, Rectangle y Triangle que hereden de Figure y implementen las operaciones específicas de cada figura.

Para manejar grupos de figuras, se puede utilizar el patrón Composite y crear una clase Group que implemente la interface Composable y permita agregar y eliminar figuras individuales del grupo. De esta manera, se pueden tratar los grupos de figuras de manera uniforme, como si fueran una sola figura, y manejarlos de manera recursiva.

Aquí está un ejemplo de implementación en Kotlin:

// Clase abstracta que representa a una figura genérica
abstract class Figure {
    abstract fun draw()
    abstract fun move(x: Int, y: Int)
    abstract fun area(): Double
}

// Clases concretas que representan figuras específicas
class Circle(val radius: Double): Figure() {
    override fun draw() = println("Dibujando círculo de radio $radius")
    override fun move(x: Int, y: Int) = println("Moviendo círculo a ($x, $y)")
    override fun area() = Math.PI * radius * radius
}

class Rectangle(val width: Double, val height: Double): Figure() {
    override fun draw() = println("Dibujando rectángulo de ancho $width y alto $height")
    override fun move(x: Int, y: Int) = println("Moviendo rectángulo a ($x, $y)")
    override fun area() = width * height
}

class Triangle(val base: Double, val height: Double): Figure() {
    override fun draw() = println("Dibujando triángulo de base $base y altura $height")
    override fun move(x: Int, y: Int) = println("Moviendo triángulo a ($x, $y)")
    override fun area() = base * height / 2
}

// Clase que representa un grupo de figuras y sus operaciones
class Group: Composable {
    private val figures = mutableListOf<Figure>()

    fun add(figure: Figure) {
        figures.add(figure)
    }

    fun remove(figure: Figure) {
        figures.remove(figure)
    }

    override fun operation() = figures.forEach { it.draw() }
}

// Creación de un grupo de figuras y su uso
fun main() {
    val group = Group()

    group.add(Circle(5.0))
    group.add(Rectangle(10.0, 5.0))
    group.add(Triangle(10.0, 5.0))

    group.operation() // Dibuja cada figura del grupo
}

En este caso, se crea un grupo de figuras y se agrega un círculo, un rectángulo y un triángulo. Luego, se llama al método operation() del grupo, que dibuja cada una de las figuras agregadas.

De esta manera, se puede tratar el grupo de figuras como si fuera una sola figura y manejarlo de manera uniforme. También se pueden crear grupos de grupos y manejarlos de manera recursiva.

Conclusión

En conclusión, el patrón Composite es una técnica útil en programación orientada a objetos para tratar grupos de objetos de manera uniforme.

Su correcta implementación puede mejorar la organización y manejo de estructuras jerárquicas en el código.

Sin embargo, es importante tener en cuenta sus desventajas y utilizarlo de manera adecuada en cada caso.

Quizá también te interese…

Setup de programador y YouTuber

Setup de programador y YouTuber

Cuando se trabaja desde casa, es importante tener un setup ordenado y que tenga un toque personal, ya que será el lugar donde pases más tiempo. En mi caso, me ha costado mucho llegar a conseguir algo limpio y funcional a la vez, ya que compagino mi faceta de...

¡Ya somos 10.000 en YouTube! [Sorteo +3.000€]

¡Ya somos 10.000 en YouTube! [Sorteo +3.000€]

Wow! Menudo viaje! Hace ya casi año y medio que empecé con el canal de DevExperto, y la verdad que no puedo estar más contento con la decisión. Durante todo este tiempo me habéis acompañado, y no habéis hecho más que darme muestras de apoyo y de agradecimiento, y ese...

0 comentarios

Enviar un comentario

Los datos personales que proporciones a través de este formulario quedarán registrados en un fichero de DevExpert, S.L.U., con el fin de gestionar los comentarios que realizas en este blog. La legitimación se realiza a través del consentimiento de la parte interesada. Si no se acepta, no podrás comentar en este blog. Los datos que proporciona solo se utilizan para evitar el correo no deseado y no se usarán para nada más. Puede ejercer los derechos de acceso, rectificación, cancelación y oposición en contacto@devexperto.com.

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Acepto la política de privacidad *