previous up next Mediator

Intent, Motivation, Applicability, Structure, Participants, Collaborations, Consequences, Implementation, Sample Code, Known Uses, Related Patterns

previous next Sample Code

We'll use a DialogDirector to implement the font dialog box shown in the Motivation. The abstract class DialogDirector defines the interface for directors.

class DialogDirector { public: virtual ~DialogDirector(); virtual void ShowDialog(); virtual void WidgetChanged(Widget*) = 0; protected: DialogDirector(); virtual void CreateWidgets() = 0; };
Widget is the abstract base class for widgets. A widget knows its director.
class Widget { public: Widget(DialogDirector*); virtual void Changed(); virtual void HandleMouse(MouseEvent& event); // ... private: DialogDirector* _director; };
Changed calls the director's WidgetChanged operation. Widgets call WidgetChanged on their director to inform it of a significant event.
void Widget::Changed () { _director->WidgetChanged(this); }
Subclasses of DialogDirector override WidgetChanged to affect the appropriate widgets. The widget passes a reference to itself as an argument to WidgetChanged to let the director identify the widget that changed. DialogDirector subclasses redefine the CreateWidgets pure virtual to construct the widgets in the dialog.

The ListBox, EntryField, and Button are subclasses of Widget for specialized user interface elements. ListBox provides a GetSelection operation to get the current selection, and EntryField's SetText operation puts new text into the field.

class ListBox : public Widget { public: ListBox(DialogDirector*); virtual const char* GetSelection(); virtual void SetList(List* listItems); virtual void HandleMouse(MouseEvent& event); // ... }; class EntryField : public Widget { public: EntryField(DialogDirector*); virtual void SetText(const char* text); virtual const char* GetText(); virtual void HandleMouse(MouseEvent& event); // ... };
Button is a simple widget that calls Changed whenever it's pressed. This gets done in its implementation of HandleMouse:
class Button : public Widget { public: Button(DialogDirector*); virtual void SetText(const char* text); virtual void HandleMouse(MouseEvent& event); // ... }; void Button::HandleMouse (MouseEvent& event) { // ... Changed(); }
The FontDialogDirector class mediates between widgets in the dialog box. FontDialogDirector is a subclass of DialogDirector:
class FontDialogDirector : public DialogDirector { public: FontDialogDirector(); virtual ~FontDialogDirector(); virtual void WidgetChanged(Widget*); protected: virtual void CreateWidgets(); private: Button* _ok; Button* _cancel; ListBox* _fontList; EntryField* _fontName; };
FontDialogDirector keeps track of the widgets it displays. It redefines CreateWidgets to create the widgets and initialize its references to them:
void FontDialogDirector::CreateWidgets () { _ok = new Button(this); _cancel = new Button(this); _fontList = new ListBox(this); _fontName = new EntryField(this); // fill the listBox with the available font names // assemble the widgets in the dialog }
WidgetChanged ensures that the widgets work together properly:
void FontDialogDirector::WidgetChanged ( Widget* theChangedWidget ) { if (theChangedWidget == _fontList) { _fontName->SetText(_fontList->GetSelection()); } else if (theChangedWidget == _ok) { // apply font change and dismiss dialog // ... } else if (theChangedWidget == _cancel) { // dismiss dialog } }
The complexity of WidgetChanged increases proportionally with the complexity of the dialog. Large dialogs are undesirable for other reasons, of course, but mediator complexity might mitigate the pattern's benefits in other applications.


Sample Code of Abstract Factory, Adapter, Bridge, Builder, Chain of Responsibility, Command, Composite, Decorator, Facade, Factory Method, Flyweight, Interpreter, Iterator, Mediator, Memento, Observer, Prototype, Proxy, Singleton, State, Strategy, Template Method, Visitor

previous next