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 |
Sí |
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:
- en el sistema desarrollado existe un grupo de objetos que pueden procesar mensajes de cierto tipo;
- todos los mensajes deben ser procesados por al menos un objeto del sistema;
- los mensajes en el sistema se procesan según el esquema “procesarlo usted mismo o pasarlo a otro”, es decir, algunos mensajes se procesan en el nivel en el que se recibieron, mientras que otros se envían a objetos de un nivel diferente.
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
- ↑ Cadena de responsabilidad en Delphi