Chain-of-responsibility pattern: Difference between revisions

Content deleted Content added
m Correctly placed method comments for EmailLogger and FileLogger methods INSIDE the method definition (just like other methods in the python snippet)
Example: add C++11 version implementation of sample code
Line 45:
The <code>receiver1</code> forwards the request to <code>receiver2</code>, which in turn forwards the request to <code>receiver3</code>, which handles (performs) the request.
 
== ExampleExamples ==
<!-- Wikipedia is not a list of examples. Do not add examples from your favorite programming language here; this page exists to explain the design pattern, not to show how it interacts with subtleties of every language under the sun. Feel free to add examples here: http://en.wikibooks.org/wiki/Computer_Science_Design_Patterns/Chain_of_responsibility -->
 
{{wikibooks|Computer Science Design Patterns|Chain of responsibility|Chain-of-responsibility implementations in various languages}}
 
=== C++ example ===
This C++11 implementation is based on the pre C++98 implementation in the book.<ref>{{cite book |author=Erich Gamma |title=Design Patterns: Elements of Reusable Object-Oriented Software |publisher=Addison Wesley |year=1994 |isbn=0-201-63361-2 |pages=189 ff.}}</ref>
<syntaxhighlight lang="c++">
#include <iostream>
#include <memory>
 
typedef int Topic;
constexpr Topic NO_HELP_TOPIC = -1;
 
// defines an interface for handling requests.
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";
// (optional) implements the successor link.
if (successor != nullptr) {
successor->handleHelp();
}
}
virtual ~HelpHandler() = default;
HelpHandler(const HelpHandler&) = delete; // rule of three
HelpHandler& operator=(const HelpHandler&) = delete;
private:
HelpHandler* successor;
Topic topic;
};
 
class Widget : public HelpHandler {
public:
Widget(const Widget&) = delete; // rule of three
Widget& operator=(const Widget&) = delete;
protected:
Widget(Widget* w, Topic t = NO_HELP_TOPIC)
: HelpHandler(w, t), parent(nullptr) {
parent = w;
}
private:
Widget* parent;
};
 
// handles requests it is responsible for.
class Button : public Widget { // ConcreteHandler
public:
Button(std::shared_ptr<Widget> h, Topic t = NO_HELP_TOPIC) : Widget(h.get(), t) {}
virtual void handleHelp() {
// 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();
}
}
};
 
class 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";
// Widget operations that Dialog overrides...
if(hasHelp()) {
// offer help on the dialog
} else {
HelpHandler::handleHelp();
}
}
};
 
class Application : public HelpHandler {
public:
Application(Topic t) : HelpHandler(nullptr, t) {}
virtual void handleHelp() {
std::cout << "Application::handleHelp\n";
// show a list of help topics
}
};
 
int main() {
constexpr Topic PRINT_TOPIC = 1;
constexpr Topic PAPER_ORIENTATION_TOPIC = 2;
constexpr Topic APPLICATION_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();
}
</syntaxhighlight>
 
The program output is:
 
<syntaxhighlight lang="c++">
Button::handleHelp
</syntaxhighlight>
 
=== Java example ===