Mediator Pattern and Multiuser Protection Billy Bennett June 8 th, 2009
Mediator
Applicability A set of objects communicates in well-defined, but complex ways. Often with unstructured dependencies. Reusing objects 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.
Participants Mediator ConcreteMediator Colleague ConcreteColleague
Structure
Consequences Limits subclassing ▫Localizes behavior that would be otherwise distributed among many objects ▫Changes in behavior require changing only the Mediator class
Consequences Decouples colleagues ▫Colleagues become more reusable. ▫You can have multiple types of interactions between colleagues, and you don’t need to subclass or otherwise change the colleague class to do that.
Consequences Simplifies object protocols ▫Many-to-many interactions replaced with one-to- many interactions ▫More intuitive ▫More extensible ▫Easier to maintain
Consequences Abstracts object cooperation ▫Mediation becomes an object itself ▫Interaction and individual behaviors are separate concepts that are encapsulated in separate objects
Consequences Centralizes control ▫Mediator can become very complex ▫With more complex interactions, extensibility and maintenance may become more difficult
Sample Code class DialogDirector { public: virtual ~DialogDirector (); virtual void ShowDialog (); virtual void WidgetChanged (Widget*) = 0; protected: DialogDirector (); virtual void CreateWidgets () = 0; }; class Widget { public: Widget (DialogDirector*); virtual void Changed (); virtual void HandleMouse (MouseEvent& event); //... private: DialogDirector* _director; }; Void Widget::Changed () { _director->WidgetChanged(this); }
Implementation Issues Omitting the abstract Mediator class – possible when only one mediator exists Strategies for Colleague-Mediator communication ▫Observer class ▫Pointer / other identifier to “self” passed from colleague to mediator, who pass it to the other colleague(s)
Related Patterns Façade ▫Unidirectional rather than cooperative interactions between object and subsystem Observer ▫May be used as a means of communication between Colleagues and the Mediator
Other thoughts Which strategy (or alternative pattern) should we use when the Mediator becomes too monolithic?
Multiuser Protection
Example from UNIX Each node in the file system has a “user” Everyone else is “other” Different actions can be assigned to “user” or to “user and other” (read, write, etc.) User defined by a unique login / password
Concrete Need security Use encapsulation Data should be inaccessible to the client Actually everything must be inaccessible to the client
Which Pattern? We’re creating an object, so probably a creational pattern Abstract factory? ▫No – we don’t need families of objects and we’re fine creating an abstract class Builder? ▫No – not an overly complex object Factory method? ▫No – similar to Abstract Factory
Which Pattern? Prototype? ▫No – addresses what, not how Singleton? ▫Ahhhhhhh – pattern designed to return a single instance of an object. ▫NOTE: Here, we’re not worried about one instance of object total, but rather per user ▫So, we can just change Instance (); static const User* User::logIn ( const string& loginName, const string& password);
Next Problem What about groups (a la UNIX)? Composite? ▫No – groups are not actually a hierarchy (no groups of groups and users may belong > 1 group) Mediator? ▫Yes – good for centralizing, objects don’t need to know about each other (no wasted resources), good security
Wrapping Up
Visitor ConcreteVisitor Composite:Component Proxy: Subject TemplateMethod:AbstractClass Visitor:Element Leaf Proxy TemplateMethod:ConcreteClass Leaf Proxy:RealSubject TemplateMethod:ConcreteClass Composite Proxy:RealSubject TemplateMethod:ConcreteClass Mediator:ConcreteColleague Singleton (variant) ConcreteMediator Singleton Mediator:ConcreteColleague