State – Patrones de Diseño

Avatar
3 min lectura

El patrón de diseño State es un patrón de comportamiento que nos permite cambiar el comportamiento de un objeto en función del estado en el que se encuentre.

Este patrón nos permite desacoplar el comportamiento de un objeto de su implementación, lo que nos permite cambiar el comportamiento de un objeto en tiempo de ejecución de forma sencilla y mantenible.

Ejemplo de State: Ascensor

Para ilustrar el uso de este patrón en Kotlin, consideremos un ejemplo de una máquina de estados finitos que simula un ascensor.

En este caso, el ascensor puede encontrarse en uno de tres estados: Subiendo, Bajando y Detenido.

Cada uno de estos estados tiene un comportamiento diferente en cuanto a la acción que debe realizar cuando se presiona un botón de piso.

Para implementar el patrón de diseño State en Kotlin, podemos utilizar una interfaz que represente el estado del ascensor y una clase que represente la máquina de estados finitos del ascensor.

La interfaz del estado del ascensor tendría un método para manejar la acción de presionar un botón de piso, y cada una de las clases que representan los estados del ascensor implementaría este método de forma diferente.

A continuación se muestra un ejemplo de cómo se podría implementar el patrón de diseño State en Kotlin para el caso del ascensor.

La interfaz ElevatorState representa un estado del ascensor y tiene un método handleFloorButtonPress() que se encarga de manejar la acción de presionar un botón de piso:

interface ElevatorState {
    fun handleFloorButtonPress(floor: Int)
}

La clase Elevator es la máquina de estados finitos del ascensor y su estado inicial es StoppedState.

class Elevator {
    var state: ElevatorState = StoppedState()

    fun pressFloorButton(floor: Int) {
        state.handleFloorButtonPress(floor)
    }
}

Este sería un ejemplo de implementación de los estados:

class StoppedState: ElevatorState {
    override fun handleFloorButtonPress(floor: Int) {
        if (floor > Elevator.currentFloor) {
            Elevator.state = GoingUpState()
        } else if (floor < Elevator.currentFloor) {
            Elevator.state = GoingDownState()
        } else {
            // Do nothing, already on the selected floor
        }
    }
}

class GoingUpState: ElevatorState {
    override fun handleFloorButtonPress(floor: Int) {
        if (floor > Elevator.currentFloor) {
            // Add floor to list of floors to visit
        } else if (floor < Elevator.currentFloor) {
            // Change direction and add floor to list of floors to visit
        } else {
            // Stop elevator on selected floor
            Elevator.state = StoppedState()
        }
    }
}

class GoingDownState: ElevatorState {
    override fun handleFloorButtonPress(floor: Int) {
        if (floor > Elevator.currentFloor) {
            // Change direction and add floor to list of floors to visit
        } else if (floor < Elevator.currentFloor) {
            // Add floor to list of floors to visit
        } else {
            // Stop elevator on selected floor
            Elevator.state = StoppedState()
        }
    }
}

Cuando se presiona un botón de piso, se llama al método pressFloorButton() de la clase Elevator, que a su vez llama al método handleFloorButtonPress() del estado actual del ascensor.

Cada una de las clases que representan los estados del ascensor implementa este método de forma diferente, de modo que el comportamiento del ascensor cambia en función del estado en el que se encuentre.

Por ejemplo, si el ascensor se encuentra en el estado StoppedState y se presiona un botón de piso en un piso superior al actual, el ascensor cambiará su estado a GoingUpState y empezará a subir.

Si en cambio se presiona un botón de piso en un piso inferior al actual, el ascensor cambiará su estado a GoingDownState y empezará a bajar.

Si se presiona un botón de piso en el mismo piso en el que se encuentra el ascensor, no se producirá ningún cambio de estado.

Conclusión

El patrón de diseño State nos permite cambiar el comportamiento de un objeto en función de su estado.

En Kotlin, podemos implementar este patrón mediante el uso de una interfaz que represente los estados del objeto y una clase que represente la máquina de estados finitos del objeto.

Cada una de las clases que representan los estados del objeto implementan el método correspondiente al comportamiento que se desea en cada estado, lo que nos permite cambiar el comportamiento del objeto en tiempo de ejecución de forma sencilla y mantenible.