Design Pattern: Chain of Responsibility
Intent:
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to
handle the request. Chain the receiving objects and pass the request along the chain until an object
handles it.
Motivation:
- Consider a context-sensitive help system. The user clicks on a part of the interface, and the
system displays help.
- If the component clicked doesn't have specific help, the system tries the container, and so on.
- This avoids hard-coding help logic for every possible UI element and allows help handling to be
spread and reused.
Structure:
- The pattern chains the receiver objects in a way that each one has a reference to the next handler.
- Each handler decides either to handle the request or to pass it to the next handler.
Participants:
1. Handler (HelpHandler)
- defines an interface for handling requests.
- optionally implements the successor link.
2. ConcreteHandler (Button, Dialog, Application)
- handles requests it is responsible for.
- can access its successor.
- if the ConcreteHandler can handle the request, it does so; otherwise it forwards the request.
Collaborations:
- A client sends a request to the first handler in the chain.
- The request propagates along the chain until a handler handles it.
Consequences:
- Reduced coupling: The sender and receiver are decoupled.
- Added flexibility: You can change the chain at runtime.
- You may not guarantee that a request will be handled.
Implementation:
- Use a base Handler class with a successor reference and a handleRequest() method.
- Subclasses override handleRequest to process or forward.
Example:
class Handler {
Handler successor;
void handleRequest() {
if (canHandle) {
// handle it
} else if (successor != null) {
successor.handleRequest();
Known Uses:
- Java's Servlet Filters
- Exception Handling in Java/.NET
Related Patterns:
- Composite: to treat nodes uniformly.
- Decorator: to add responsibilities, but differs in intent.
- Command: can use a chain to execute a command.
- Mediator: distributes logic to a central mediator rather than a chain.
Mediator Pattern
Intent:
Mediator defines an object that encapsulates how a set of objects interact. It promotes loose
coupling by preventing objects from referring to each other directly.
Motivation:
In complex systems like GUI dialogs, widgets (buttons, text fields, etc.) often depend on each other.
Without a mediator, these interconnections become hard to manage and reuse. Mediator centralizes
control, reducing direct dependencies.
Example:
In a FontDialog, a FontDialogDirector acts as the mediator coordinating widgets like ListBox,
EntryField, and Button.
When to Use:
- Complex inter-object communication
- Hard to reuse objects due to tight coupling
- You want to avoid subclassing just to change interaction behavior
Participants:
- Mediator ? Interface for communication
- ConcreteMediator ? Coordinates colleague objects
- Colleagues ? Widgets/components that communicate via the mediator
Benefits:
1. Reduces subclassing
2. Promotes loose coupling
3. Simplifies object communication
4. Centralizes control and coordination
Drawback:
Mediator can become complex and hard to maintain if too much logic is centralized.
Related Patterns:
- Observer ? Used for communication
- Facade ? Simplifies interface (but one-way), unlike Mediator (two-way)