Cadena de Responsabilidades

La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la versión revisada el 27 de julio de 2013; las comprobaciones requieren 27 ediciones .
Cadena de Responsabilidades
Cadena de responsabilidad
Tipo de conductual
Objetivo para la organización en el sistema de niveles de responsabilidad
Plantillas relacionadas enlazador
Descrito en Patrones de diseño

La cadena de responsabilidad es un  patrón de diseño de comportamiento diseñado para organizar los niveles de responsabilidad en un sistema.

Aplicación

Se recomienda el uso de la plantilla en las siguientes condiciones:

Ejemplos

Ejemplo de Delphi

Código fuente en Delphi patrón de unidad ; _ interfaz utiliza SysUtils ; escribe TPurchase = número público de clase : entero ; Cantidad : Doble ; Propósito : cadena _ constructor Create ( num : integer ; am : Double ; pur : string ) ; fin ; IApprover = interfaz [ '{3ACA3967-FFCF-48A1-AC45-9A9B98A8DD96}' ] procedimiento SetSuccessor ( sucesor : IApprover ) ; procedimiento ProcessRequest ( compra : TCompra ) ; fin ; TApprover = clase ( TInterfacedObject , IApprover ) protected FSuccessor : IApprover ; procedimiento público SetSuccessor ( sucesor : IApprover ) ; procedimiento ProcessRequest ( compra : TCompra ) ; virtuales ; abstracto ; fin ; TDirector = clase ( TApprover ) procedimiento ProcessRequest ( compra : TPurchase ) ; anular ; fin ; TVicePresident = clase ( TApprover ) procedimiento ProcessRequest ( compra : TPurchase ) ; anular ; fin ; TPresident = clase ( TApprover ) procedimiento ProcessRequest ( compra : TPurchase ) ; anular ; fin ; implementación { TApprover } procedimiento TApprover . SetSuccessor ( sucesor : IApprover ) ; comenzar FSuccessor := sucesor ; fin ; { TDirector } procedimiento TDirector . ProcessRequest ( compra : TPurchase ) ; comenzar si compra . Importe < 1000 0.0 luego WriteLn ( Formato ( 'Solicitud aprobada por el director n.° %d' , [ compra . Número ])) de lo contrario, si FSuccessor <> nil , entonces FSuccessor . ProcessRequest ( compra ) ; fin ; {TVicepresidente} procedimiento TVicepresidente . ProcessRequest ( compra : TPurchase ) ; comenzar si compra . Cantidad < 2500 0.0 luego WriteLn ( Formato ( 'Vicepresidente aprobó solicitud # %d' , [ compra . Número ])) de lo contrario si FSuccessor <> nil entonces FSuccessor . ProcessRequest ( compra ) ; fin ; {TPresidente} procedimiento TPresidente . ProcessRequest ( compra : TPurchase ) ; comenzar si compra . Amount < 10000 0.0 then WriteLn ( Format ( 'Solicitud aprobada por el presidente # %d' , [ compra . Número ])) else WriteLn ( Format ( 'Solicitud # %d requiere una reunión ejecutiva!' , [ compra . Número ])) end ; { TComprar } constructor TPurchase . Crear ( num : entero ; am : Doble ; pur : cadena ) ; ComienzoNumero : = num ; Importe := am ; Propósito := pur ; fin ; fin _ //________________________________________________________________________ programa conductual . CadenaDeResponsabilidad . patrón ; {$CONSOLA DE TIPO DE APLICACIÓN} usa SysUtils , Pattern en 'Pattern.pas' ; varDirector : Aprobador ; _ Vicepresidente : I Aprobador ; Presidente : Yo Aprobador ; Compra : TCompra ; comenzar ReportMemoryLeaksOnShutDown := DebugHook <> 0 ; intente Director := TDirector . crear ; Vicepresidente := TVicepresidente . crear ; Presidente := TPresidente . crear ; intentarDirector . _ SetSuccessor ( Vicepresidente ) ; vicepresidente _ SetSuccessor ( Presidente ) ; Compra := TCompra . Crear ( 2034 , 35 0.00 , 'Suministros' ) ; directora _ ProcessRequest ( Compra ) ; compra _ Gratis ; Compra := TCompra . Crear ( 2035 , 3259 0.10 , 'Proyecto X' ) ; directora _ ProcessRequest ( Compra ) ; compra _ Gratis ; Compra := TCompra . Crear ( 2036 , 12210 0.00 , 'Proyecto Y' ) ; directora _ ProcessRequest ( Compra ) ; Leerln ; Finalmente compra . Gratis ; fin ; excepto en E : Exception do Writeln ( E . Classname , ': ' , E . Message ) ; fin ; fin _

Ejemplo de PHP 5

Código fuente en PHP 5.3 espacio de nombres ChainOfResponsibility { Registrador de clase abstracta { constERR = 3 ; _ const AVISO = 5 ; const DEPURAR = 7 ; máscara de $ protegida ; // El siguiente elemento en la cadena de responsabilidades protected $next ; public function __construct ( $mask ) { $this -> mask = $mask ; } public function setNext ( Logger $log ) { $this -> next = $log ; devolver $registro ; } mensaje de función pública ( $msg , $priority ) { if ( $priority <= $this -> mask ) { $this -> writeMessage ( $msg ); } if ( $esto -> siguiente != nulo ) { $esto -> siguiente -> mensaje ( $ mensaje , $prioridad ); } } función abstracta protegida escribirMensaje ( $msg ); } clase StdoutLogger extiende registrador { función protegida writeMessage ( $msg ) { echo sprintf ( "Escribiendo en stdout:%s \n " , $msg ); } } clase EmailLogger extiende registrador { función protegida escribirMensaje ( $msg ) { echo sprintf ( "Enviando por correo electrónico:%s \n " , $msg ); } } clase StderrLogger extiende registrador { función protegida escribirMensaje ( $msg ) { echo sprintf ( "Enviando a stderr:%s \n " , $msg ); } } //cadena de responsabilidades class ChainOfResponsibilityExample { función pública ejecutar () { // construye la cadena de responsabilidad $logger = new StdoutLogger ( Logger :: DEBUG ); $logger1 = $logger -> setNext ( new EmailLogger ( Logger :: AVISO )); $logger2 = $logger1 -> setNext ( nuevo StderrLogger ( Logger :: ERR )); // Manejado por StdoutLogger $logger -> mensaje ( "Ingresando a la función y." , Logger :: DEBUG ); // Manejado por StdoutLogger y EmailLogger $logger -> mensaje ( "Paso 1 completado". , Logger :: AVISO ); // Manejado por los tres registradores $logger -> mensaje ( "Ha ocurrido un error." , Logger :: ERR ); } } $cadena = new ChainOfResponsibilityExample (); $cadena -> ejecutar (); }

Ejemplo de Java

Fuente Java paquete cadenaofresp ; Registrador de clase abstracta { public static int ERR = 3 ; public static int AVISO = 5 ; public static int DEBUG = 7 ; máscara interna protegida ; _ // El siguiente elemento en la cadena de responsabilidad protected Logger next ; Registrador público setNext ( registro del registrador ) { siguiente = registro ; registro de retorno ; } mensaje público vacío ( String msg , int prioridad ) { if ( prioridad <= máscara ) { writeMessage ( msg ); } if ( siguiente != nulo ) { siguiente . mensaje ( mensaje , prioridad ); } } abstract protected void writeMessage ( String msg ); } class StdoutLogger extiende el registrador { public StdoutLogger ( int mask ) { this . máscara = máscara ; } protect void writeMessage ( String msg ) { System . fuera _ println ( "Escribiendo en stdout:" + msg ); } } class EmailLogger extiende registrador { public EmailLogger ( int mask ) { this . máscara = máscara ; } protect void writeMessage ( String msg ) { System . fuera _ println ( "Enviando por correo electrónico: " + msj ); } } clase StderrLogger extiende Logger { public StderrLogger ( int mask ) { this . máscara = máscara ; } protect void writeMessage ( String msg ) { System . fuera _ println ( "Enviando a stderr:" + msg ); } } public class ChainOfResponsibilityExample { public static void main ( String [] args ) { // Construir la cadena de responsabilidad Logger logger , logger1 , logger2 ; registrador = nuevo StdoutLogger ( registrador . DEBUG ); registrador1 = registrador . setNext ( nuevo EmailLogger ( Registrador . AVISO )); registrador2 = registrador1 . setNext ( nuevo StderrLogger ( Registrador . ERR )); // Manejado por el registrador StdoutLogger . mensaje ( "Ingresando a la función y." , Registrador . DEBUG ); // Manejado por el registrador StdoutLogger y EmailLogger . mensaje ( "Paso 1 completado." , Registrador . AVISO ); // Manejado por los tres registradores registrador . mensaje ( "Ha ocurrido un error." , Registrador . ERR ); } } /* La salida es: Escribiendo en stdout: Ingresando a la función y. Escribiendo en stdout: Paso 1 completado. Envío por correo electrónico: Paso 1 completado. Escribiendo en stdout: Se ha producido un error. Envío por correo electrónico: Se ha producido un error. Enviando a stderr: Se ha producido un error. */

Ejemplo en C#

Texto fuente en C# // Patrón de Cadena de Responsabilidad -- Ejemplo estructural utilizando el sistema ; espacio de nombres DoFactory.GangOfFour.Chain.Structural { /// <summary> /// Clase de inicio de MainApp para Structural /// Patrón de diseño de cadena de responsabilidad. /// </summary> class MainApp { /// <summary> /// Punto de entrada a la aplicación de consola. /// </summary> static void Main () { // Configuración de la cadena del controlador de responsabilidad h1 = new ConcreteHandler1 ( ); Manejador h2 = nuevo ManejadorConcreto2 (); Manejador h3 = nuevo ManejadorConcreto3 (); h1 _ EstablecerSucesor ( h2 ); h2 _ EstablecerSucesor ( h3 ); // Generar y procesar solicitud int [] solicitudes = { 2 , 5 , 14 , 22 , 18 , 3 , 27 , 20 }; foreach ( int solicitud en solicitudes ) { h1 . ManejarSolicitud ( solicitud ); } // Esperar a la Consola del usuario . Clave de lectura (); } } /// <summary> /// La clase abstracta 'Manejador' /// </summary> clase abstracta Manejador { protected Manejador sucesor ; public void SetSuccessor ( sucesor del controlador ) { this . sucesor = sucesor ; } public abstract void HandleRequest ( solicitud int ); } /// <summary> /// La clase 'ConcreteHandler1' /// </summary> class ConcreteHandler1 : Handler { public override void HandleRequest ( int request ) { if ( request >= 0 && request < 10 ) { Console . WriteLine ( "{0} solicitud manejada {1}" , this . GetType (). Nombre , solicitud ); } else if ( sucesor != nulo ) { sucesor . ManejarSolicitud ( solicitud ); } } } /// <summary> /// La clase 'ConcreteHandler2' /// </summary> class ConcreteHandler2 : Handler { public override void HandleRequest ( int request ) { if ( request >= 10 && request < 20 ) { Console . WriteLine ( "{0} solicitud manejada {1}" , this . GetType (). Nombre , solicitud ); } else if ( sucesor != nulo ) { sucesor . ManejarSolicitud ( solicitud ); } } } /// <summary> /// La clase 'ConcreteHandler3' /// </summary> class ConcreteHandler3 : Handler { public override void HandleRequest ( int request ) { if ( request >= 20 && request < 30 ) { Console . WriteLine ( "{0} solicitud manejada {1}" , this . GetType (). Nombre , solicitud ); } else if ( sucesor != nulo ) { sucesor . ManejarSolicitud ( solicitud ); } } } } Salida Solicitud manejada por ConcreteHandler1 2 Solicitud manejada por ConcreteHandler1 5 Solicitud manejada por ConcreteHandler2 14 Solicitud manejada por ConcreteHandler3 22 Solicitud manejada por ConcreteHandler2 18 Solicitud manejada por ConcreteHandler1 3 Solicitud manejada por ConcreteHandler3 27 Solicitud manejada por ConcreteHandler3 20

Ejemplo de C++

Texto fuente en C++ #incluir <iostream> /** * Clase de ayudante que describe algún crimen */ clase AcciónCriminal { policía de clase amiga ; // La policía tiene acceso a los materiales de la investigación complejidad int ; // Complejidad del caso const char * descripción ; // Breve descripción del crimen público : CriminalAction ( int complejidad , const char * descripción ) : complejidad ( complejidad ), descripción ( descripción ) {} }; /** * Un oficial de policía abstracto que puede investigar crímenes */ policía de clase { protegido : reducción de int ; // deducción (la capacidad de desentrañar casos complejos) para este policía Policía * siguiente ; // un policía más hábil que conseguirá un caso si es demasiado difícil para el actual investigarConcreto de vacío virtual ( const char * descripción ) {} // investigación real público : Policía ( int deducción ) : deducción ( deducción ), siguiente ( nullptr ) {} virtual ~ policía () { borrar siguiente ; } /** * Añade a la cadena de responsabilidad a un policía con más experiencia que puede hacerse cargo * de la investigación si la actual falla */ Policía * setNext ( Policía * policía ) { siguiente = policía ; volver a continuación ; } /** * El oficial de policía inicia una investigación o, si el caso es demasiado complicado, se lo pasa a un colega más experimentado */ anular investigar ( CriminalAction * criminalAction ) { if ( deducción < criminalAcción -> complejidad ) { si ( siguiente ) { siguiente -> investigar ( criminalAction ); } más { std :: cout << "Este caso no debe ser revelado a nadie". << estándar :: endl ; } } más { investigarConcreto ( accióncriminal -> descripción ); } } }; clase MartinRiggs : policía público { protegido : void investigarConcreto ( const char * descripción ) { std :: cout << "Investigación del caso \" " << descripción << " \" dirigida por el sargento Martin Riggs" << std :: endl ; } público : MartinRiggs ( deducción int ) : Policía ( deducción ) {} }; clase JohnMcClane : policía público { protegido : void investigarConcreto ( const char * descripción ) { std :: cout << "Investigación \" " << descripción << " \" Detective John McClane" << std :: endl ; } público : John McClane ( deducción int ) : Policía ( deducción ) {} }; clase Vincent Hanna : policía público { protegido : void investigarConcreto ( const char * descripción ) { std :: cout << "Investigación del caso \" " << descripción << " \" dirigida por el teniente Vincent Hanna" << std :: endl ; } público : VincentHanna ( deducción int ) : Policía ( deducción ) {} }; int principal () { std :: cout << "SALIDA:" << std :: endl ; Policía * policía = nuevo MartinRiggs ( 3 ); // policía con la menor habilidad investigativa policía -> establecerSiguiente ( nuevo JohnMcClane ( 5 )) -> establecerSiguiente ( nuevo Vincent Hanna ( 8 )); // agregarle dos colegas policías experimentados - > investigar ( new CriminalAction ( 2 , "Drug Traffic from Vietnam" )); policía -> investigar ( new CriminalAction ( 7 , "Un audaz robo a un banco en el centro de Los Ángeles" )); policía -> investigar ( nuevo CriminalAction ( 5 , "Serie de explosiones en el centro de Nueva York" )); devolver 0 ; } /** * RESULTADO: * Investigando el tráfico de drogas en Vietnam por el sargento Martin Riggs * Investigando el atrevido robo a un banco en el centro de Los Ángeles por el teniente Vincent Hanna * Investigando una serie de atentados con bomba en el centro de Nueva York presentado por el detective John McClain */

Ejemplo de Python

Código fuente en Python manipuladores = [] def car_handler ( func ): manejadores . agregar ( función ) devolver función clase Coche : def __init__ ( auto ): auto . nombre = Ninguno propio . km = 11100 auto . combustible = 5 auto . aceite = 5 @car_handler def handle_fuel ( coche ): si coche . combustible < 10 : print ( "combustible añadido" ) coche . combustible = 100 @car_handler def handle_km ( coche ): si coche . km > 10000 : print ( "hizo una prueba de carro" ) carro . km = 0 @car_handler def handle_oil ( coche ): si coche . aceite < 10 : print ( "Aceite añadido" ) coche . aceite = 100 class Garage : def __init__ ( self , handlers = None ): self . manejadores = manejadores o [] def add_handler ( self , handler ): self . manipuladores _ agregar ( manejador ) def handle_car ( self , car ): para handler en self . manipuladores : manipulador ( coche ) if __name__ == '__principal__' : garaje = Garaje ( manejadores ) coche = Coche () garaje . handle_car ( coche )

Enlaces

Notas

  1. Cadena de responsabilidad en Delphi