- Chain of Responsibility (patrón de diseño)
-
El patrón de diseño Chain of Responsibility permite establecer una cadena de objetos receptores a través de los cuales se pasa una petición formulada por un objeto emisor. Cualquiera de los objetos receptores puede responder a la petición en función de un criterio establecido.
Contenido
Motivación
Se utiliza, por ejemplo, cuando en función del estado del sistema las peticiones emitidas por un objeto deben ser atendidas por distintos objetos receptores.
Estructura
Implementación
Todos los objetos receptores implementarán la misma interfaz o extenderán la misma clase abstracta. En ambos casos se proveerá de un método que permita obtener el sucesor y así el paso de la petición por la cadena será lo más flexible y transparente posible.
Ejemplos
Java
/** * The Chain of responsibility pattern is based on several classes that know about their next * brother class. If a class cannot process a request, another one will. * @author Politron * */ public class ChainOfResponsabilityPattern { public void main(String args[]){ new A("C"); } public abstract class Letter{ String letter; abstract public void checkLetter(); } public class A extends Letter{ public A(String letter){ this.letter = letter; checkLetter(); } public void checkLetter() { if(!letter.equals("A")){ new B(letter);//Next Chain }else{ System.out.print("Here we have " + letter); } } } public class B extends Letter{ public B(String letter){ this.letter = letter; checkLetter(); } public void checkLetter() { if(!letter.equals("B")){ new C(letter);//Next Chain }else{ System.out.print("Here we have " + letter); } } } public class C extends Letter{ public C(String letter){ this.letter = letter; checkLetter(); } public void checkLetter() { if(letter.equals("C")){ System.out.print("Check with numbers dude!!"); } } }
El siguiente código java muestra un ejemplo de este patrón para una clase que hace un 'log'. Cada elemento de log decide si debe de mostrar el log dependiendo de su nivel de log y pasa el mensaje al siguiente elemento. La salida será:
Escribiendo en DEBUG: Entrando en function y. Escribiendo en DEBUG: Paso 1 completado Escribiendo en STDERR: Paso 1 completado. Escribiendo en DEBUG: Ha ocurrido un error. Enviando un e-mail: Ha ocurrido un error. Escribiendo en STDERR: Ha ocurrido un error.
Observese que una implementación 'pura' de este patrón detendría la cadena. En este ejemplo no ocurre así.
También notar que si fuera un implementación 'pura', habría que cambiar el orden en la creación del objeto Logger l, pues en este caso, nunca se llegaría a lanzar message de la clase StderrLogger, pues tiene un nivel menos importante (mask=5) que su predecesor EMailLogger (mask=3)
import java.util.*; abstract class Logger { public static int ERR = 3; public static int NOTICE = 5; public static int DEBUG = 7; protected int mask; protected Logger next; // el siguiente elemento en la cadena public Logger setNext(Logger l) { next = l; return this; } abstract public void message(String msg, int priority); } class DebugLogger extends Logger{ public DebugLogger(int mask) { this.mask = mask; } public void message(String msg, int priority) { if (priority <= mask) System.out.println("Escribiendo en DEBUG: " + msg); if (next != null) next.message(msg, priority); } } class EMailLogger extends Logger{ public EMailLogger(int mask) { this.mask = mask; } public void message(String msg, int priority) { if (priority <= mask) System.out.println("Enviando un e-mail: " + msg); if (next != null) next.message(msg, priority); } } class StderrLogger extends Logger{ public StderrLogger(int mask) { this.mask = mask; } public void message(String msg, int priority) { if (priority <= mask) System.out.println("Escribiendo en STDERR: " + msg); if (next != null) next.message(msg, priority); } } class ChainOfResponsibilityExample{ public static void main(String[] args) { // Construimos la cadena // DebugLogger(DEBUG = 7) => EMailLogger(Error = 3) => StderrLogger(Notice = 5) Logger l = new DebugLogger(Logger.DEBUG).setNext( new EMailLogger(Logger.ERR).setNext( new StderrLogger(Logger.NOTICE) ) ); // Ejecutamos l.message("Entrando en function y.", Logger.DEBUG); // manejado por DebugLogger l.message("paso 1 completado.", Logger.NOTICE); // manejado por DebugLogger y StderrLogger l.message("Ha ocurrido un error.", Logger.ERR); // menejado por los tres Logger } }
Categoría:- Patrones de diseño
Wikimedia foundation. 2010.