Mediator Design Pattern in C++
Mediator design pattern demo
Discussion. Though partitioning a system into many objects generally enhances reusability, proliferating interconnections tend to reduce it again. You can avoid this problem by encapsulating the interconnections (i.e. the collective behavior) in a separate "mediator" object. A mediator is responsible for controlling and coordinating the interactions of a group of objects.
In this example, the dialog box
object is functioning as the mediator. Child widgets of the dialog box
do not know, or care, who their siblings are. Whenever a simulated
user interaction occurs in a child widget Widget::changed()
, the
widget does nothing except "delegate" that event to its parent dialog
box mediator->widgetChanged(this)
.
FileSelectionDialog::widgetChanged()
encapsulates all collective
behavior for the dialog box (it serves as the hub of communication).
The user may choose to "interact" with a simulated: filter edit field,
directories list, files list, or selection edit field.
#include <iostream.h>
class FileSelectionDialog;
class Widget
{
public:
Widget(FileSelectionDialog *mediator, char *name)
{
_mediator = mediator;
strcpy(_name, name);
}
virtual void changed();
virtual void updateWidget() = 0;
virtual void queryWidget() = 0;
protected:
char _name[20];
private:
FileSelectionDialog *_mediator;
};
class List: public Widget
{
public:
List(FileSelectionDialog *dir, char *name): Widget(dir, name){}
void queryWidget()
{
cout << " " << _name << " list queried" << endl;
}
void updateWidget()
{
cout << " " << _name << " list updated" << endl;
}
};
class Edit: public Widget
{
public:
Edit(FileSelectionDialog *dir, char *name): Widget(dir, name){}
void queryWidget()
{
cout << " " << _name << " edit queried" << endl;
}
void updateWidget()
{
cout << " " << _name << " edit updated" << endl;
}
};
class FileSelectionDialog
{
public:
enum Widgets
{
FilterEdit, DirList, FileList, SelectionEdit
};
FileSelectionDialog()
{
_components[FilterEdit] = new Edit(this, "filter");
_components[DirList] = new List(this, "dir");
_components[FileList] = new List(this, "file");
_components[SelectionEdit] = new Edit(this, "selection");
}
virtual ~FileSelectionDialog();
void handleEvent(int which)
{
_components[which]->changed();
}
virtual void widgetChanged(Widget *theChangedWidget)
{
if (theChangedWidget == _components[FilterEdit])
{
_components[FilterEdit]->queryWidget();
_components[DirList]->updateWidget();
_components[FileList]->updateWidget();
_components[SelectionEdit]->updateWidget();
}
else if (theChangedWidget == _components[DirList])
{
_components[DirList]->queryWidget();
_components[FileList]->updateWidget();
_components[FilterEdit]->updateWidget();
_components[SelectionEdit]->updateWidget();
}
else if (theChangedWidget == _components[FileList])
{
_components[FileList]->queryWidget();
_components[SelectionEdit]->updateWidget();
}
else if (theChangedWidget == _components[SelectionEdit])
{
_components[SelectionEdit]->queryWidget();
cout << " file opened" << endl;
}
}
private:
Widget *_components[4];
};
FileSelectionDialog::~FileSelectionDialog()
{
for (int i = 0; i < 4; i++)
delete _components[i];
}
void Widget::changed()
{
_mediator->widgetChanged(this);
}
int main()
{
FileSelectionDialog fileDialog;
int i;
cout << "Exit[0], Filter[1], Dir[2], File[3], Selection[4]: ";
cin >> i;
while (i)
{
fileDialog.handleEvent(i - 1);
cout << "Exit[0], Filter[1], Dir[2], File[3], Selection[4]: ";
cin >> i;
}
}
Output
Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 1 filter edit queried dir list updated file list updated selection edit updated Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 2 dir list queried file list updated filter edit updated selection edit updated Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 3 file list queried selection edit updated Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 4 selection edit queried file opened Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 3 file list queried selection edit updated