Chain-of-responsibility pattern

Last updated

In object-oriented design, the chain-of-responsibility pattern is a behavioral design pattern consisting of a source of command objects and a series of processing objects. [1] Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain. A mechanism also exists for adding new processing objects to the end of this chain.

Contents

In a variation of the standard chain-of-responsibility model, some handlers may act as dispatchers, capable of sending commands out in a variety of directions, forming a tree of responsibility. In some cases, this can occur recursively, with processing objects calling higher-up processing objects with commands that attempt to solve some smaller part of the problem; in this case recursion continues until the command is processed, or the entire tree has been explored. An XML interpreter might work in this manner.

This pattern promotes the idea of loose coupling.

The chain-of-responsibility pattern is structurally nearly identical to the decorator pattern, the difference being that for the decorator, all classes handle the request, while for the chain of responsibility, exactly one of the classes in the chain handles the request. This is a strict definition of the Responsibility concept in the GoF book. However, many implementations (such as loggers below, or UI event handling, or servlet filters in Java, etc.) allow several elements in the chain to take responsibility.

Overview

The Chain of Responsibility [2] design pattern is one of the twenty-three well-known GoF design patterns that describe common solutions to recurring design problems when designing flexible and reusable object-oriented software, that is, objects that are easier to implement, change, test, and reuse.

What problems can the Chain of Responsibility design pattern solve?

Implementing a request directly within the class that sends the request is inflexible because it couples the class to a particular receiver and makes it impossible to support multiple receivers. [3]

What solution does the Chain of Responsibility design pattern describe?

This enables us to send a request to a chain of receivers without having to know which one handles the request. The request gets passed along the chain until a receiver handles the request. The sender of a request is no longer coupled to a particular receiver.

See also the UML class and sequence diagram below.

Structure

UML class and sequence diagram

A sample UML class and sequence diagram for the Chain of Responsibility design pattern. W3sDesign Chain of Responsibility Design Pattern UML.jpg
A sample UML class and sequence diagram for the Chain of Responsibility design pattern.

In the above UML class diagram, the Sender class doesn't refer to a particular receiver class directly. Instead, Sender refers to the Handler interface for handling a request (handler.handleRequest()), which makes the Sender independent of which receiver handles the request. The Receiver1, Receiver2, and Receiver3 classes implement the Handler interface by either handling or forwarding a request (depending on run-time conditions).
The UML sequence diagram shows the run-time interactions: In this example, the Sender object calls handleRequest() on the receiver1 object (of type Handler). The receiver1 forwards the request to receiver2, which in turn forwards the request to receiver3, which handles (performs) the request.

Example

This C++11 implementation is based on the pre C++98 implementation in the book. [5]

#include<iostream>#include<memory>typedefintTopic;constexprTopicNO_HELP_TOPIC=-1;// defines an interface for handling requests.classHelpHandler{// Handlerpublic:HelpHandler(HelpHandler*h=nullptr,Topict=NO_HELP_TOPIC):successor(h),topic(t){}virtualboolhasHelp(){returntopic!=NO_HELP_TOPIC;}virtualvoidsetHandler(HelpHandler*,Topic){}virtualvoidhandleHelp(){std::cout<<"HelpHandler::handleHelp\n";// (optional) implements the successor link.if(successor!=nullptr){successor->handleHelp();}}virtual~HelpHandler()=default;HelpHandler(constHelpHandler&)=delete;// rule of threeHelpHandler&operator=(constHelpHandler&)=delete;private:HelpHandler*successor;Topictopic;};classWidget:publicHelpHandler{public:Widget(constWidget&)=delete;// rule of threeWidget&operator=(constWidget&)=delete;protected:Widget(Widget*w,Topict=NO_HELP_TOPIC):HelpHandler(w,t),parent(nullptr){parent=w;}private:Widget*parent;};// handles requests it is responsible for.classButton:publicWidget{// ConcreteHandlerpublic:Button(std::shared_ptr<Widget>h,Topict=NO_HELP_TOPIC):Widget(h.get(),t){}virtualvoidhandleHelp(){// if the ConcreteHandler can handle the request, it does so; otherwise it forwards the request to its successor.std::cout<<"Button::handleHelp\n";if(hasHelp()){// handles requests it is responsible for.}else{// can access its successor.HelpHandler::handleHelp();}}};classDialog:publicWidget{// ConcreteHandlerpublic:Dialog(std::shared_ptr<HelpHandler>h,Topict=NO_HELP_TOPIC):Widget(nullptr){setHandler(h.get(),t);}virtualvoidhandleHelp(){std::cout<<"Dialog::handleHelp\n";// Widget operations that Dialog overrides...if(hasHelp()){// offer help on the dialog}else{HelpHandler::handleHelp();}}};classApplication:publicHelpHandler{public:Application(Topict):HelpHandler(nullptr,t){}virtualvoidhandleHelp(){std::cout<<"Application::handleHelp\n";// show a list of help topics}};intmain(){constexprTopicPRINT_TOPIC=1;constexprTopicPAPER_ORIENTATION_TOPIC=2;constexprTopicAPPLICATION_TOPIC=3;// The smart pointers prevent memory leaks.std::shared_ptr<Application>application=std::make_shared<Application>(APPLICATION_TOPIC);std::shared_ptr<Dialog>dialog=std::make_shared<Dialog>(application,PRINT_TOPIC);std::shared_ptr<Button>button=std::make_shared<Button>(dialog,PAPER_ORIENTATION_TOPIC);button->handleHelp();}

Implementations

Cocoa and Cocoa Touch

The Cocoa and Cocoa Touch frameworks, used for OS X and iOS applications respectively, actively use the chain-of-responsibility pattern for handling events. Objects that participate in the chain are called responder objects, inheriting from the NSResponder (OS X)/UIResponder (iOS) class. All view objects (NSView/UIView), view controller objects (NSViewController/UIViewController), window objects (NSWindow/UIWindow), and the application object (NSApplication/UIApplication) are responder objects.

Typically, when a view receives an event which it can't handle, it dispatches it to its superview until it reaches the view controller or window object. If the window can't handle the event, the event is dispatched to the application object, which is the last object in the chain. For example:

See also

Related Research Articles

<span class="mw-page-title-main">Abstract factory pattern</span> Software design pattern

The abstract factory pattern in software engineering is a design pattern that provides a way to create families of related objects without imposing their concrete classes, by encapsulating a group of individual factories that have a common theme without specifying their concrete classes. According to this pattern, a client software component creates a concrete implementation of the abstract factory and then uses the generic interface of the factory to create the concrete objects that are part of the family. The client does not know which concrete objects it receives from each of these internal factories, as it uses only the generic interfaces of their products. This pattern separates the details of implementation of a set of objects from their general usage and relies on object composition, as object creation is implemented in methods exposed in the factory interface.

<span class="mw-page-title-main">Singleton pattern</span> Design pattern in object-oriented software development

In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to a singular instance. One of the well-known "Gang of Four" design patterns, which describes how to solve recurring problems in object-oriented software, the pattern is useful when exactly one object is needed to coordinate actions across a system.

In object oriented programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify their exact class. Rather than by calling a constructor, this is done by calling a factory method to create an object. Factory methods can either be specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes.

The prototype pattern is a creational design pattern in software development. It is used when the types of objects to create is determined by a prototypical instance, which is cloned to produce new objects. This pattern is used to avoid subclasses of an object creator in the client application, like the factory method pattern does, and to avoid the inherent cost of creating a new object in the standard way when it is prohibitively expensive for a given application.

In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes a group of objects that are treated the same way as a single instance of the same type of object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.

In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other instances of the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern as well as to the Open-Closed Principle, by allowing the functionality of a class to be extended without being modified. Decorator use can be more efficient than subclassing, because an object's behavior can be augmented without defining an entirely new object.

In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time. This information includes the method name, the object that owns the method and values for the method parameters.

In computer programming, the interpreter pattern is a design pattern that specifies how to evaluate sentences in a language. The basic idea is to have a class for each symbol in a specialized computer language. The syntax tree of a sentence in the language is an instance of the composite pattern and is used to evaluate (interpret) the sentence for a client. See also Composite pattern.

In object-oriented programming, the template method is one of the behavioral design patterns identified by Gamma et al. in the book Design Patterns. The template method is a method in a superclass, usually an abstract superclass, and defines the skeleton of an operation in terms of a number of high-level steps. These steps are themselves implemented by additional helper methods in the same class as the template method.

Template metaprogramming (TMP) is a metaprogramming technique in which templates are used by a compiler to generate temporary source code, which is merged by the compiler with the rest of the source code and then compiled. The output of these templates can include compile-time constants, data structures, and complete functions. The use of templates can be thought of as compile-time polymorphism. The technique is used by a number of languages, the best-known being C++, but also Curl, D, Nim, and XL.

<span class="mw-page-title-main">Model–view–controller</span> Software design pattern

Model–view–controller (MVC) is a software design pattern commonly used for developing user interfaces that divides the related program logic into three interconnected elements. These elements are:

In computer programming, run-time type information or run-time type identification (RTTI) is a feature of some programming languages that exposes information about an object's data type at runtime. Run-time type information may be available for all types or only to types that explicitly have it. Run-time type information is a specialization of a more general concept called type introspection.

gtkmm is the official C++ interface for the popular GUI library GTK. gtkmm is free software distributed under the GNU Lesser General Public License (LGPL).

In computer programming, an opaque pointer is a special case of an opaque data type, a data type declared to be a pointer to a record or data structure of some unspecified type.

The curiously recurring template pattern (CRTP) is an idiom, originally in C++, in which a class X derives from a class template instantiation using X itself as a template argument. More generally it is known as F-bound polymorphism, and it is a form of F-bounded quantification.

C++11 is a version of the ISO/IEC 14882 standard for the C++ programming language. C++11 replaced the prior version of the C++ standard, called C++03, and was later replaced by C++14. The name follows the tradition of naming language versions by the publication year of the specification, though it was formerly named C++0x because it was expected to be published before 2010.

The front controller software design pattern is listed in several pattern catalogs and is related to the design of web applications. It is "a controller that handles all requests for a website," which is a useful structure for web application developers to achieve flexibility and reuse without code redundancy.

Wt is an open-source widget-centric web framework for the C++ programming language. It has an API resembling that of Qt framework, also using a widget-tree and an event-driven signal/slot system.

C++23 is the informal name for the version of the International Organization for Standardization (ISO) and International Electrotechnical Commission (IEC) 14882 standard for the C++ programming language that follows C++20. The final draft of this version is N4950.

Pattern-Oriented Software Architecture is a series of software engineering books describing software design patterns.

References

  1. "Chain of Responsibility Design Pattern". Archived from the original on 2018-02-27. Retrieved 2013-11-08.
  2. Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Design Patterns: Elements of Reusable Object-Oriented Software . Addison Wesley. pp.  223ff. ISBN   0-201-63361-2.{{cite book}}: CS1 maint: multiple names: authors list (link)
  3. "The Chain of Responsibility design pattern - Problem, Solution, and Applicability". w3sDesign.com. Retrieved 2017-08-12.
  4. "The Chain of Responsibility design pattern - Structure and Collaboration". w3sDesign.com. Retrieved 2017-08-12.
  5. Erich Gamma (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley. pp. 189 ff. ISBN   0-201-63361-2.