stringtranslate.com

Patrón de cadena de responsabilidad

En el diseño orientado a objetos , el patrón de cadena de responsabilidad es un patrón de diseño de comportamiento que consta de una fuente de objetos de comando y una serie de objetos de procesamiento . [1] Cada objeto de procesamiento contiene una lógica que define los tipos de objetos de comando que puede manejar; el resto se pasa al siguiente objeto de procesamiento en la cadena. También existe un mecanismo para agregar nuevos objetos de procesamiento al final de esta cadena.

En una variación del modelo estándar de cadena de responsabilidades, algunos controladores pueden actuar como despachadores , capaces de enviar comandos en una variedad de direcciones, formando un árbol de responsabilidades . En algunos casos, esto puede ocurrir de forma recursiva, con objetos de procesamiento que llaman a objetos de procesamiento superiores con comandos que intentan resolver una parte más pequeña del problema; en este caso, la recursión continúa hasta que se procesa el comando o se ha explorado todo el árbol. Un intérprete XML podría funcionar de esta manera.

Este patrón promueve la idea de acoplamiento flexible .

El patrón de cadena de responsabilidad es estructuralmente casi idéntico al patrón de decorador , la diferencia es que para el decorador, todas las clases manejan la solicitud, mientras que para la cadena de responsabilidad, exactamente una de las clases en la cadena maneja la solicitud. Esta es una definición estricta del concepto de Responsabilidad en el libro de GoF . Sin embargo, muchas implementaciones (como los registradores a continuación, o el manejo de eventos de UI, o los filtros de servlets en Java, etc.) permiten que varios elementos en la cadena asuman la responsabilidad.

Descripción general

El patrón de diseño Cadena de Responsabilidad [2] es uno de los veintitrés patrones de diseño GoF conocidos que describen soluciones comunes a problemas de diseño recurrentes al diseñar software orientado a objetos flexible y reutilizable, es decir, objetos que son más fáciles de implementar, cambiar, probar y reutilizar.

¿Qué problemas puede resolver el patrón de diseño Cadena de Responsabilidad?

Implementar una solicitud directamente dentro de la clase que envía la solicitud es inflexible porque acopla la clase a un receptor particular y hace imposible admitir múltiples receptores. [3]

¿Qué solución describe el patrón de diseño Cadena de Responsabilidad?

Esto nos permite enviar una solicitud a una cadena de receptores sin tener que saber cuál de ellos la gestiona. La solicitud se transmite a lo largo de la cadena hasta que un receptor la gestiona. El remitente de una solicitud ya no está asociado a un receptor en particular.

Vea también el diagrama de clases y secuencias UML a continuación.

Estructura

Diagrama de clases y secuencias UML

Un ejemplo de diagrama de clase y secuencia UML para el patrón de diseño Cadena de responsabilidad. [4]

En el diagrama de clases UML anterior , la clase no hace referencia directamente a una clase receptora en particular. En cambio, hace referencia a la interfaz para manejar una solicitud ( ), lo que hace que la clase sea independiente de qué receptor maneja la solicitud. Las clases , y implementan la interfaz manejando o reenviando una solicitud (según las condiciones de tiempo de ejecución). El diagrama de secuencia UML muestra las interacciones en tiempo de ejecución: En este ejemplo, el objeto llama al objeto (de tipo ). El reenvía la solicitud a , que a su vez reenvía la solicitud a , que maneja (realiza) la solicitud.SenderSenderHandlerhandler.handleRequest()SenderReceiver1Receiver2Receiver3Handler
SenderhandleRequest()receiver1Handlerreceiver1receiver2receiver3

Ejemplo

Esta implementación de C++11 se basa en la implementación anterior a C++98 del libro. [5]

#include <iostream> #include <memoria>  typedef int Tema ; constexpr Tema NO_HELP_TOPIC = -1 ;      // define una interfaz para manejar solicitudes. class HelpHandler { // Handler public : HelpHandler ( HelpHandler * h = nullptr , Topic t = NO_HELP_TOPIC ) : successor ( h ), topic ( t ) {} virtual bool hasHelp () { return topic != NO_HELP_TOPIC ; } virtual void setHandler ( HelpHandler * , Topic ) {} virtual void handleHelp () { std :: cout << "HelpHandler::handleHelp \n " ; // (opcional) implementa el enlace sucesor. if ( successor != nullptr ) { successor -> handleHelp (); } } virtual ~ HelpHandler () = default ; HelpHandler ( const HelpHandler & ) = delete ; // regla de tres HelpHandler & operator = ( const HelpHandler & ) = delete ; private : HelpHandler * successor ; Topic topic ; };                                                               clase Widget : público HelpHandler { público : Widget ( const Widget & ) = eliminar ; // regla de tres Widget & operador = ( const Widget & ) = eliminar ; protegido : Widget ( Widget * w , Tema t = NO_HELP_TOPIC ) : HelpHandler ( w , t ), padre ( nullptr ) { padre = w ; } privado : Widget * padre ; };                                 // maneja las solicitudes de las que es responsable. class Button : public Widget { // ConcreteHandler public : Button ( std :: shared_ptr < Widget > h , Topic t = NO_HELP_TOPIC ) : Widget ( h . get (), t ) {} virtual void handleHelp () { // si ConcreteHandler puede manejar la solicitud, lo hace; de ​​lo contrario, reenvía la solicitud a su sucesor. std :: cout << "Button::handleHelp \n " ; if ( hasHelp ()) { // maneja las solicitudes de las que es responsable. } else { // puede acceder a su sucesor. HelpHandler :: handleHelp (); } } };                                    clase Dialog : public Widget { // ConcreteHandler public : Dialog ( std :: shared_ptr < HelpHandler > h , Topic t = NO_HELP_TOPIC ) : Widget ( nullptr ) { setHandler ( h.get ( ), t ); } virtual void handleHelp () { std :: cout << "Dialog::handleHelp \n " ; // Operaciones del widget que Dialog anula... if ( hasHelp ()) { // ofrecer ayuda sobre el diálogo } else { HelpHandler :: handleHelp (); } } };                                   clase Aplicación : público HelpHandler { público : Aplicación ( Tema t ) : HelpHandler ( nullptr , t ) {} virtual void handleHelp () { std :: cout << "Aplicación::handleHelp \n " ; // mostrar una lista de temas de ayuda } };                    int main () { constexpr Tema TEMA_IMPRIMIR = 1 ; constexpr Tema TEMA_ORIENTACIÓN_PAPEL = 2 ; constexpr Tema TEMA_APLICACIÓN = 3 ; // Los punteros inteligentes evitan fugas de memoria. std :: shared_ptr < Aplicación > aplicación = std :: make_shared < Aplicación > ( TEMA_APLICACIÓN ); std :: shared_ptr < Diálogo > diálogo = std :: make_shared < Diálogo > ( aplicación , TEMA_IMPRIMIR ); std :: shared_ptr < Botón > botón = std :: make_shared < Botón > ( diálogo , TEMA_ORIENTACIÓN_PAPEL );                                 botón -> handleHelp (); }

Implementaciones

Cacao y toque de cacao

Los frameworks Cocoa y Cocoa Touch , utilizados para aplicaciones OS X e iOS respectivamente, utilizan activamente el patrón de cadena de responsabilidad para gestionar eventos. Los objetos que participan en la cadena se denominan objetos respondedores y heredan de la clase NSResponder(OS X)/ UIResponder(iOS). Todos los objetos de vista ( NSView/ UIView), objetos de controlador de vista ( NSViewController/ UIViewController), objetos de ventana ( NSWindow/ UIWindow) y el objeto de aplicación ( NSApplication/ UIApplication) son objetos respondedores.

Normalmente, cuando una vista recibe un evento que no puede controlar, lo envía a su supervista hasta que llega al controlador de vista o al objeto de ventana. Si la ventana no puede controlar el evento, el evento se envía al objeto de aplicación, que es el último objeto de la cadena. Por ejemplo:

Véase también

Referencias

  1. ^ "Patrón de diseño de la cadena de responsabilidad". Archivado desde el original el 27 de febrero de 2018. Consultado el 8 de noviembre de 2013 .
  2. ^ Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Patrones de diseño: elementos de software reutilizable orientado a objetos . Addison Wesley. pp. 223ff. ISBN 0-201-63361-2.{{cite book}}: CS1 maint: varios nombres: lista de autores ( enlace )
  3. ^ "El patrón de diseño Cadena de responsabilidad: problema, solución y aplicabilidad". w3sDesign.com . Consultado el 12 de agosto de 2017 .
  4. ^ "El patrón de diseño Cadena de responsabilidad: estructura y colaboración". w3sDesign.com . Consultado el 12 de agosto de 2017 .
  5. ^ Erich Gamma (1994). Patrones de diseño: elementos de software reutilizable orientado a objetos . Addison Wesley. pp. 189 y siguientes. ISBN 0-201-63361-2.