informaticaPC

Patrones de Diseño Software


Regístrate

Tus datos no serán compartidos, solo nosotros te enviaremos información y novedades

Chain of Responsability

Este patrón puede resultarnos útil en casos en los que un objeto emisor de una petición desconozca qué objeto(s) podrá(n) atender a la misma.

A continuación mostramos un ejemplo de uso en lenguaje Java:

Chain of Responsability en UML

Main.java (Cliente en el diagrama anterior):

package ChainOfResponsability1;

public class Main
{
    public static void main(String[] args)
    {
        Manejador m1 = new ManejadorAprobado();
        Manejador m2 = new ManejadorDenegado();
        Manejador m3 = new ManejadorPendiente();

        m1.setSiguiente( m2 );
        m2.setSiguiente( m3 );

        m1.comprobar("APROBADO");
        m1.comprobar("APROBADO");
        m1.comprobar("DENEGADO");
        m1.comprobar(null);
        m1.comprobar("DENEGADO");
    }
}

Manejador.java:

package ChainOfResponsability1;

public abstract class Manejador
{
    protected Manejador siguienteManejador;

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

    public Manejador getSiguiente() {
        return this.siguienteManejador;
    }

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

    public void setSiguiente(Manejador m) {
        this.siguienteManejador = m;
    }

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

    public abstract void comprobar(String estado);
}

ManejadorAprobado.java (un ManejadorConcreto en el diagrama anterior):

package ChainOfResponsability1;

public class ManejadorAprobado extends Manejador
{
    public ManejadorAprobado() {
    }

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

    @Override
    public void comprobar(String estado)
    {
       if( (estado != null) && (estado.equalsIgnoreCase("APROBADO") == true) )
       {
           System.out.println("Solicitud aprobada");
       }
       else
       {
            if( this.getSiguiente() != null )
            {
                // Llamamos al método en el siguiente objeto
                this.getSiguiente().comprobar( estado );
            }
       }
    }
}

ManejadorDenegado.java (un ManejadorConcreto en el diagrama anterior):

package ChainOfResponsability1;

public class ManejadorDenegado extends Manejador
{
    public ManejadorDenegado() {
    }

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

    @Override
    public void comprobar(String estado)
    {
       if( (estado != null) && (estado.equalsIgnoreCase("DENEGADO") == true) )
       {
           System.out.println("Solicitud denegada");
       }
       else
       {
            if( this.getSiguiente() != null )
            {
                // Llamamos al método en el siguiente objeto
                this.getSiguiente().comprobar( estado );
            }
       }
    }
}

ManejadorPendiente.java (un ManejadorConcreto en el diagrama anterior):

package ChainOfResponsability1;

public class ManejadorPendiente extends Manejador
{
    public ManejadorPendiente() {
    }

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

    @Override
    public void comprobar(String estado)
    {
       if( estado == null )
       {
           System.out.println("Solicitud pendiente");
       }
       else
       {
            if( this.getSiguiente() != null )
            {
                // Llamamos al método en el siguiente objeto
                this.getSiguiente().comprobar( estado );
            }
       }
    }
}

Al ejecutarlo obtendríamos como resultado:

Ejemplo

EXPLICACIÓN:

  • En la clase abstracta Manejador definimos el método comprobar() que deberán implementar las clases a partir de las cuales crearemos los objetos de dicho tipo.
  • En dicho método se realizará la comprobación necesaria en cada caso para verificar si el objeto actual debe procesar la petición. En caso contrario, se pasará la misma al siguiente objeto de la cadena.
  • En dicha clase definimos también los métodos 'set' y 'get' para establecer y obtener el siguiente objeto al que el actual deberá pasar la petición que ha recibido.
  • En el programa principal se crean los objetos que formarán parte de la cadena de responsabilidad, utilizando el método setSiguiente() para indicar a cada uno de ellos cuál es el siguiente en la misma.

En el ejemplo anterior, cuando un objeto procesa la petición ésta no se continúa pasando al resto de ellos. Para implementar dicha funcionalidad bastaría con quitar el 'else' en el método comprobar() de cada clase.

Veamos un ejemplo de cómo hacerlo:

Main.java (Cliente en el diagrama anterior):

package ChainOfResponsability2;

public class Main
{
    public static void main(String[] args)
    {
        Manejador m1 = new ManejadorPositivo();
        Manejador m2 = new ManejadorNegativo();
        Manejador m3 = new ManejadorRangoPositivo();

        m1.setSiguiente( m2 );
        m2.setSiguiente( m3 );

        m1.comprobar(60);
        m1.comprobar(-30);
        m1.comprobar(40);
    }
}

Manejador.java:

package ChainOfResponsability2;

public abstract class Manejador
{
    protected Manejador siguienteManejador;

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

    public Manejador getSiguiente() {
        return this.siguienteManejador;
    }

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

    public void setSiguiente(Manejador m) {
        this.siguienteManejador = m;
    }

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

    public abstract void comprobar(int numero);
}

ManejadorPositivo.java (un ManejadorConcreto en el diagrama anterior):

package ChainOfResponsability2;

public class ManejadorPositivo extends Manejador
{
    public ManejadorPositivo() {
    }

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

    @Override
    public void comprobar(int numero)
    {
        if( numero>0 ) {
           System.out.println("El número es positivo");
        }

        if( this.getSiguiente() != null ) {
            this.getSiguiente().comprobar( numero );
        }
    }
}

ManejadorNegativo.java (un ManejadorConcreto en el diagrama anterior):

package ChainOfResponsability2;

public class ManejadorNegativo extends Manejador
{
    public ManejadorNegativo() {
    }

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

    @Override
    public void comprobar(int numero)
    {
       if( numero<0 ) {
           System.out.println("El número es negativo");
       }

        if( this.getSiguiente() != null ) {
            this.getSiguiente().comprobar( numero );
        }
    }
}

ManejadorRangoPositivo.java (un ManejadorConcreto en el diagrama anterior):

package ChainOfResponsability2;

public class ManejadorRangoPositivo extends Manejador
{
    public ManejadorRangoPositivo() {
    }

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

    @Override
    public void comprobar(int numero)
    {
        if( numero>0 && numero<=50 ) {
           System.out.println("El número está entre 1 y 50");
        }

        if( this.getSiguiente() != null ) {
            this.getSiguiente().comprobar( numero );
        }
    }
}

Al ejecutarlo obtendríamos como resultado:

Ejemplo

Otra forma de implementar este patrón es creando un método en la clase abstracta que será utilizado para enviar la petición (en lugar de que lo haga cada ManejadorConcreto, como en el ejemplo anterior).

Veamos a continuación un ejemplo de cómo hacerlo.

Main.java (Cliente en el diagrama anterior):

package ChainOfResponsability3;

public class Main
{
    public static void main(String[] args)
    {
        Manejador m1 = new ManejadorPositivo();
        Manejador m2 = new ManejadorNegativo();
        Manejador m3 = new ManejadorRangoPositivo();

        m1.setSiguiente( m2 );
        m2.setSiguiente( m3 );

        m1.procesar(60);
        m1.procesar(-30);
        m1.procesar(40);
    }
}

Manejador.java:

package ChainOfResponsability3;

public abstract class Manejador
{
    protected Manejador siguienteManejador;

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

    public Manejador getSiguiente() {
        return this.siguienteManejador;
    }

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

    public void setSiguiente(Manejador m) {
        this.siguienteManejador = m;
    }

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

    public void procesar(int numero)
    {
        if( numero>=-100 && numero<=100) {
            this.comprobar(numero);
        }

        if (this.getSiguiente() != null) {
            this.getSiguiente().procesar( numero );
        }
    }

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

    public abstract void comprobar(int numero);
}

ManejadorNegativo.java (un ManejadorConcreto en el diagrama anterior):

package ChainOfResponsability3;

public class ManejadorNegativo extends Manejador
{
    public ManejadorNegativo() {
    }

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

    @Override
    public void comprobar(int numero)
    {
       if( numero<0 ) {
           System.out.println("El número es negativo");
       }
    }
}

ManejadorPositivo.java (un ManejadorConcreto en el diagrama anterior):

package ChainOfResponsability3;

public class ManejadorPositivo extends Manejador
{
    public ManejadorPositivo() {
    }

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

    @Override
    public void comprobar(int numero)
    {
        if( numero>0 ) {
           System.out.println("El número es positivo");
        }
    }
}

ManejadorRangoPositivo.java (un ManejadorConcreto en el diagrama anterior):

package ChainOfResponsability3;

public class ManejadorRangoPositivo extends Manejador
{
    public ManejadorRangoPositivo() {
    }

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

    @Override
    public void comprobar(int numero)
    {
        if( numero>0 && numero<=50 ) {
           System.out.println("El número está entre 1 y 50");
        }
    }
}

Al ejecutarlo obtendríamos el mismo resultado que en el caso anterior:

Ejemplo

EXPLICACIÓN:

  • En la clase abstracta Manejador definimos el método procesar() en el que comprobamos si el valor recibido es válido: si lo es lo envía al método que lo procesa, y de lo contrario lo pasa al siguiente objeto en la cadena de responsabilidad (si lo hubiere).
Primera página Anterior Siguiente Última página
Usamos cookies para ofrecerte una experiencia mejorada, el continuar navegando supone que aceptas su uso