// Purpose. Mediator // // Discussion. On the left: Node objs #include // interact directly with each other, // recursion is required, removing a class Node { // Node is hard, and it is not possi- public: // ble to remove the first node. On Node( int v ) { val_ = v; } // the right: a "mediating" List class int getVal() { return val_; } // focuses and simplifies all the ad- private: // ministrative responsibilities, and int val_; // the recursion (which does not scale }; // up well) has been eliminated. class List { #include public: List() { class Node { for (int i=0; i < 10; i++) public: arr_[i] = 0; Node( int v, Node* n ) { num_ = 0; val_ = v; } next_ = n; void addNode( Node* n ) { } arr_[num_++] = n; void traverse() { } cout << val_ << " "; void traverse() { if (next_) for (int i=0; i < num_; i++) next_->traverse(); cout << arr_[i]->getVal() else << " "; cout << endl; cout << endl; } } void removeNode( int v ) { void removeNode( int v ) { Node* ptr = (Node*) 1; int i, j; removeNode_( v, &ptr ); for (i=0; i < num_; i++) } if (arr_[i]->getVal() == v) private: { int val_; for (j=i; j < num_; j++) Node* next_; arr_[j] = arr_[j+1]; void removeNode_(int v, Node** n) { num_--; if (val_ == v) break; *n = next_; } else } { private: next_->removeNode_( v, n ); Node* arr_[10]; if (*n != (Node*) 1) int num_; { }; next_ = *n; *n = (Node*) 1; void main( void ) } { } List lst; } Node one( 11 ), two( 22 ); }; Node thr( 33 ), fou( 44 ); lst.addNode( &one ); void main( void ) lst.addNode( &two ); { lst.addNode( &thr ); Node fou( 44, 0 ); lst.addNode( &fou ); Node thr( 33, &fou ); lst.traverse(); Node two( 22, &thr ); lst.removeNode( 44 ); Node one( 11, &two ); lst.traverse(); one.traverse(); lst.removeNode( 11 ); one.removeNode( 44 ); lst.traverse(); one.traverse(); } one.removeNode( 22 ); one.traverse(); // 11 22 33 44 } // 11 22 33 // 22 33 // 11 22 33 44 // 11 22 33 // 11 33 // Purpose. 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 capsulating 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 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 < 3; i++) delete _components[i]; } void Widget::changed() { _mediator->widgetChanged( this ); } void 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; } } // 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