informaticaPC

Patrones de Diseño Software

State

Este patrón resulta útil cuando necesitamos que un objeto se comporte de forma diferente dependiendo del estado interno en el que se encuentre en cada momento.

Según el siguiente diagrama en UML podemos apreciar que el objeto cuyo estado es susceptible de cambiar (Contexto) contendrá una referencia a otro objeto que define los distintos tipos de estado en que se puede encontrar.

State en UML

Pero para comprenderlo mejor veamos un sencillo ejemplo en el que controlamos el estado de un semáforo:

Main.java:

package State;

public class Main
{
    public static void main(String[] args)
    {
        Semaforo objSemaforo = new Semaforo();

        // Muestra el aviso por defecto (verde, no hay alerta)
        objSemaforo.mostrar();

        objSemaforo.setEstado( new EstadoNaranja() );
        objSemaforo.mostrar();

        objSemaforo.setEstado( new EstadoRojo() );
        objSemaforo.mostrar();
    }
}

Semaforo.java (Contexto según el diagrama anterior):

package State;

public class Semaforo
{
    private EstadoSemaforo objEstadoSemaforo;

    // -------------------------------------------

    public Semaforo() {
        this.objEstadoSemaforo = new EstadoVerde();
    }

    // -------------------------------------------

    public void setEstado( EstadoSemaforo objEstadoSemaforo ) {
        this.objEstadoSemaforo = objEstadoSemaforo;
    }

    // -------------------------------------------

    @Override
    public void mostrar() {
        this.objEstadoSemaforo.mostrar();
    }
}

EstadoSemaforo.java (Estado según el diagrama anterior):

Package State;

public abstract class EstadoSemaforo
{
    // Método que deberán crear las clases que hereden de ésta
    public abstract void mostrar();
}

EstadoVerde.java (un EstadoConcreto según el diagrama anterior):

package State;

public class EstadoVerde extends EstadoSemaforo
{
    public EstadoVerde() {
    }

    // -------------------------------------------

    @Override
    public void mostrar() {
        System.out.println("Luz verde");
    }
}

EstadoNaranja.java (un EstadoConcreto según el diagrama anterior):

package State;

public class EstadoVerde extends EstadoSemaforo
{
    public EstadoVerde() {
    }

    // -------------------------------------------

    @Override
    public void mostrar() {
        System.out.println("Luz naranja");
    }
}

EstadoRojo.java (un EstadoConcreto según el diagrama anterior):

package State;

public class EstadoVerde extends EstadoSemaforo
{
    public EstadoVerde() {
    }

    // -------------------------------------------

    @Override
    public void mostrar() {
        System.out.println("Luz roja");
    }
}

Al ejecutarlo obtendríamos como resultado:

Ejemplo

EXPLICACIÓN:

  • Al inicio del programa se crea un objeto de tipo Semaforo (que al ser instanciado quedará por defecto en EstadoVerde) y mostramos el aviso visual correspondiente. Posteriormente cambiamos otras dos veces su estado.
  • De este modo se mostrará un aviso u otro dependiendo dependiendo del estado de Semaforo en un momento dado.
  • Observa que en la propiedad estado_actual de Semaforo queda registrado el estado del mismo en todo momento.

En este otro ejemplo realizamos una modificación en el anterior de modo que cada objeto de tipo EstadoSemaforo contenga una referencia al objeto que lo utiliza:

Main.java:

package State2;

public class Main
{
    public static void main(String[] args)
    {
        Semaforo objSemaforo = new Semaforo();

        // Muestra el aviso por defecto (verde, no hay alerta)
        objSemaforo.mostrarAviso();

        objSemaforo.setEstado( new EstadoNaranja(objSemaforo) );
        objSemaforo.mostrarAviso();

        objSemaforo.setEstado( new EstadoRojo(objSemaforo) );
        objSemaforo.mostrarAviso();
    }
}

Semaforo.java (Contexto según el diagrama UML anterior):

package State2;

public class Semaforo
{
    private EstadoSemaforo objEstadoSemaforo;

    // -------------------------------------------

    public Semaforo() {
        this.objEstadoSemaforo = new EstadoVerde(this);
    }

    // -------------------------------------------

    public void setEstado( EstadoSemaforo objEstadoSemaforo ) {
        this.objEstadoSemaforo = objEstadoSemaforo;
    }

    // -------------------------------------------

    public void mostrarAviso() {
        this.objEstadoSemaforo.mostrar();
    }
}

EstadoSemaforo.java (Estado según el diagrama UML anterior):

package State2;

public abstract class EstadoSemaforo
{
    protected Semaforo objSemaforo;

    // Método que deberán crear las clases que hereden de ésta
    public abstract void mostrar();
}

EstadoVerde.java (un EstadoConcreto según el diagrama UML anterior):

package State2;

public class EstadoVerde extends EstadoSemaforo
{
    public EstadoVerde( Semaforo objSemaforo ) {
        this.objSemaforo = objSemaforo;
    }

    // -------------------------------------------

    @Override
    public void mostrar() {
        System.out.println("No estamos en alerta");
    }
}

EstadoNaranja.java (un EstadoConcreto según el diagrama UML anterior):

package State2;

public class EstadoNaranja extends EstadoSemaforo
{
    public EstadoNaranja( Semaforo objSemaforo ) {
        this.objSemaforo = objSemaforo;
    }

    // -------------------------------------------

    @Override
    public void mostrar() {
        System.out.println("Alerta naranja");
    }

EstadoRojo.java (un EstadoConcreto según el diagrama UML anterior):

package State2;

public class EstadoRojo extends EstadoSemaforo
{
    public EstadoRojo( Semaforo objSemaforo ) {
        this.objSemaforo = objSemaforo;
    }

    // -------------------------------------------

    @Override
    public void mostrar() {
        System.out.println("Alerta roja");
    }
}

EXPLICACIÓN: en este caso a la hora de cambiar el estado de un objeto de tipo Semaforo, a la instancia de estado que le pasamos como parámetro le agregamos una referencia a dicho objeto, quedando registrada en la propiedad objSemaforo de ésta, de forma que en caso necesario pueda acceder a su contenedor.

Información

Este patrón de diseño es parecido al patrón Strategy, en el que se crea un objeto indicando el comportamiento que deberá tener, pero sin la posibilidad de ser modificado posteriormente.

Primera página Anterior Siguiente Última página
Usamos cookies para ofrecerte una experiencia mejorada, el continuar navegando supone que aceptas su uso