190 likes | 286 Views
Chain of Responsibility Pattern. Gof pp. 223-232 Yuyang Chen. Chain of Responsibility Pattern. Chain of Responsibility Pattern. Intent
E N D
Chain of Responsibility Pattern Gof pp. 223-232 Yuyang Chen
Chain of Responsibility Pattern • Intent • Avoid coupling sender of request to its receiver by giving more than one object chance to handle request. Chain receiving objects and pass request along until an object handles it.
Chain of Responsibility Pattern • Motivation: • Book Example – Consider context-sensitive help for graphical user interface • Let’s say user clicks on a help button – help provided depends on the button clicks • Help request is handled by one of several user interface objects, but which one depends on context and specificity of available help. • Problem is that object that provides help isn’t known by the object that request help.
Chain of Responsibility Pattern • Description • Decouple senders and receivers by giving multiple objects (in a set order) a chance to handle a request. Request passed until an object handles it. • 1st object in chain receives request – either handles it or forwards to next object in chain. • Object that makes request has no explicit knowledge of who will handle it – request has an implicit receiver.
Chain of Responsibility Pattern Request Handled! Request!
Chain of Responsibility Pattern • Structure
Chain of Responsibility Pattern Participants: • Handler – defines interface for handling requests. Can also implement successor link • ConcreteHandler – handles requests it is responsible for; otherwise forwards requests to successor. • Client – initiates request to a ConcreteHandler in the chain.
Chain of Responsibility Pattern • Use Chain of Responsibility when: • More than 1 object may handle a request, and handle isn’t known beforehand. • Want to issue request to one of several objects without specifying receiver explicitly. • Set of objects that can handle a request should be specificed dynamically
Chain of Responsibility Pattern CONSEQUENCES • Benefits: • Decoupling of senders and receivers • Added flexibility • Sender doesn’t need to know specifically who the handlers are • Potential Drawbacks: • Client can’t explicity specify who handles a request • No guarantee of request being handled (request falls off end of chain)
Chain of Responsibility Pattern Implementation • How to implement the successor chain? • Define new links (in Handler or ConcreteHandler) • Use existing links (such as the parent references from the Composite pattern)
Chain of Responsibility Pattern • Sample Code: class HelpHandler { public: HelpHandler(HelpHandler* s) : _successor(s) { } virtual void HandleHelp(); private: HelpHandler* _successor; }; void HelpHandler::HandleHelp() { if(_successor) { _succeessor->HandleHelp(); } }
Chain of Responsibility Pattern • Representing Requests • Request can be hard-coded operation. This is convenient and safe, but can only forward fixed set of requests that Handler class defines. • Can use separate request objects that contain all request parameters; these must have accessor functions that return an identifier for the class
Chain of Responsibility Pattern void Handler::HandleRequest (Request * theRequest) { switch (theRequest->GetKind() ) { case Help: // cast argument ot appropriate type HandleHelp( (HelpRequest*) theRequest); break; case Print: HandlePrint((PrintRequest*) theRequest); // etc . . . } Subclasses can extend this by overriding HandleRequest to handle only the requests in which the subclass is interested.