COSC 3351 Software Design Design Patterns Behavioral Patterns (I) Spring 2008 Purpose Creational Structural Behavioral Scope Class Factory Method Adapter(class) Interpreter Template Method Object Abstract Factory Adapter(object) Chain of Responsibility Builder Bridge Command Prototype Composite Iterator Singleton Decorator Mediator Façade Flyweight Proxy Observer State Strategy Visitor Memento 1
Behavioral Patterns Deal with how classes and objects interact with each other Sharing responsibilities between objects and classes characterize (complex) flow control between objects and classes 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 Applicability: Use the Chain of Responsibility pattern if More than one object may handle the request, and the handler isn t known a priori You want to issue a request to one of several objects without specifying the receiver explicitly. The set of objects that can handle a request should be specified dynamically 2
Structure Client Handler HandlerRequest() ConcreteHandler1 ConcreteHandler2 HandlerRequest() HandlerRequest() : Client : ConcreteHandler1 : ConcreteHandler2 HandleRequest() HandleRequest() Participants Handler: defines an interface for handling requests (optionally) implements the successor link ConcreteHandler: Handles requests it is responsible fors Can access its successor If the ConcreteHandler can handle the request, it does so; else it forwards the request to its successor. Client: initiates the request to a ConcreteHandler object on a chain 3
Example A context sensitive Help System Depending on where you are in the GUI you get different screens when pressing on the help button If no specific help information exists for that part of the interface, the help system should display a general help message about the immediate context Problem: the object that ultimately provides the help information is unknown to the object (i.e. the button) that initiates the help request. -> Decouples sender and receiver typedef int Topic; const Topic NO_HELP_TOPIC = -1; class HelpHandler { public: HelpHandler( HelpHandler*=0, Topic=NO_HELP_TOPIC); virtual bool HasHelp (); virtual void SetHandler (HelpHandler*, Topic); virtual void Handlehelp (); private: HelpHandler* _successor; Topic _topic; HelpHandler:: HelpHandler (HelpHandler* h, Topic t): _successor(h), _topic(t) { bool HelpHandler::HasHelp () { return (_topic!= NO_HELP_TOPIC); void HelpHandler:: HandleHelp() { if ( _successor!= 0 ) { _successor->handlehelp(); 4
class Widget: Public HelpHandler { protected: Widget( Wdiget* parent, Topic t=no_help_topic); private: Widget* _parent; Widget:: Widget (Widget *w, Topic t): HelpHandler(w,t){ _parent = w; class Button : public Widget { public: Button (Widget *d, Topic t=no_help_topic); virtual void HandleHelp(); Button::Button (Widget *d, Topic t) : Widget (d,t) { void Button::HandleHelp() { if ( HasHelp() ) { //offer help on the Button else { HelpHandler::HandleHelp(); // Application is not a widget class Application: Public HelpHandler { public: Application(Topic t): HelpHandler(0,t); virtual void HandleHelp(); void Application::HandleHelp() { // print list of topics, do not forward // Code to set up the chain of HelpHandlers Application *app = new Application (APPLICATION_TOPIC); Button *button1 = new Button ( app, PRINT_TOPIC); Button *button2 = new Button ( button1, PAPER_ORIENTATION); a call to button2->handlehelp will initiate the chain 5
Command Intent: encapsulate a request as an object, thereby letting you parameterize clients with different requests queue or log requests support undo-operations Also known as: Transaction pattern Structure Invoker Command Client Execute() Action() Receiver ConcreteCommand state Execute() 6
Participants Command: declares an interface for executing an operation ConcreteCommand: defines a binding between the Receiver object and an action implements Execute by invoking the corresponding operation on Receiver Client: create a ConcreteCommand object and its receiver Invoker: asks the command to carry out the request Receiver: knows how to perform the operation associated with carrying out a request Example: A graphical User Interface Each choice in a Menu is an instance of a MenuItem class An Application class creates the MenuItems along with the rest of the interface keeps track of the Document objects that are open configures each MenuItem with a concrete Command subclass When the user selects a MenuItem, the MenuItem calls Execute of the on its command subclass, which carries out the operation 7
Outline Application Menu MenuItem Command Add() Add(MenuItem) Clicked() Execute() Document command->execute() Open() Close() Cut() Copy() Paste() Document Open() Close() Cut() Copy() Paste() PasteCommand Execute() Command Execute() OpenCommand Execute() AskUser() document->paste() name = AskUser(); doc = new Document(name); application->add(doc); doc->open(); 8
Supporting Undo The Command pattern can support Undo and redo operations have to provide a way to reverse execution in the Command interface might require storage of additional state, such as the Receiver object arguments to the operation performed on the receiver any original values in the receiver History list, if more than one operation should be undoable Undoable command might have to copy entire objects before being placed on the history list i.e. for undoing delete operation Mediator Intent: define an object that encapsulates how a set of objects interact Applicability: use the Mediator pattern when a set of objects communicate in a well-defined but complex way. The resulting interdependencies are unstructured and difficult to understand reusing an object is difficult because it refers to and communicates with many other objects a behavior that s distributed between several classes should be customizable without a lot of subclassing 9
Structure Mediator Colleague ConcreteMediator ConcreteCollegue1 ConcreteCollegue2 Participants Mediator: defines an interface fo communicating between Colleague objects ConcreteMediator: implements cooperative behavior by Coordinating Colleague objects ConcreteColleagues: each Colleague knows it Mediator object each colleague communicates with its mediator whenever it would have otherwise communicated with another colleague 10
Consequences The Mediator pattern: limits subclassing by localizing behavior that otherwise would be distributed among multiple objects decouples colleagues simplifies the object protocol, since it replaces many-tomany interactions with one-to-many interactions abstracts away how objects cooperate centralizes control the mediator pattern trades complexity of interaction for complexity in the mediator the class can become a lot more complex than any individual colleague! Observer Intent: define a one-to-many dependency between objects so that when one objects changes state, all its dependents are notified and updates automatically Applicability: Use the observer pattern when an abstraction has two aspects, one dependent on another then changes to one object require changing other objects, and you don t know how many objects need to be changed when an object should be able to notify other objects without making assumptions about who these objects are. 11
Structure Subject Attach(Observer) Detach(Observer) Notify() for all o in observer { o->update() Observer Update() ConcreteSubject subjectstate GetState() SetState() return subjectstate; ConcreteObserver observerstate Update() observerstate = subject->getstate(); Participants Subject: knows its observers. Any number of Observer objects may observe a subject provides an interface for attaching and detaching Observer objects Observer: defines an updating interface for objects that should be notified of changes in a subject ConcreteSubject: stores state of interest to ConcreteObserver objects sends a notification to its observers when its state changes ConcreteObserver: maintains a reference to a ConcreteSubject object stores state that should stay consistent with subject implements the Observers updating interface to keep its state consistent with the subject 12
Who triggers the update? Option 1: make state-setting operations on Subject call Notify() automatically clients don t need to remember to call Notify several consecutive operations will cause several consecutive updates, although they could be bundled. Option 2: make the client call the update operation solves the multi-update problem more error prone Push vs. Pull model Push Model: subject sends observers detailed information about the change subject does not distinguish whether the observers is interested in all type of state changes Pull Model: subject only minimal notification observer asks for details for events of interest 3 rd Alternative: introduce the notion of interest in the Attach operation of a subject, e.g. void Subject::Attach ( Observer*, Aspect& interest); 13
ChangeManager Additional entity introduced when dependency relations between subjects and observers are complex Responsibilities: map a subject to its observers and provide an interface to maintain this mapping define particular update strategies update all dependent observers at the request of a subject ChangeManager often acts as mediator between subjects and observers, since it encapsulates complex update semantics ChangeManager is usually unique, i.e. it may use the Singleton pattern Model-View-Controller: Model is the subject View is the Observer Example 14