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…

Test Driven Development [TDD] – Qué es y cómo aplicarlo

Test Driven Development [TDD] – Qué es y cómo aplicarlo

TDD (Test Driven Development) es un enfoque de desarrollo de software en el que los desarrolladores escriben primero las pruebas antes de escribir el código. La idea es escribir las pruebas primero para asegurarse de que el código cumpla con los requisitos específicos...

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 *