Sono nuovo per progettare modelli, ecco un classico esempio di modello di mediatore di base che ha 3 problemi con esso, prima di tutto guarda l'immagine dell'applicazione, il diagramma, il codice e la descrizione:
Utilizziamo DialogDirector per implementare la finestra di dialogo dei caratteri mostrata nella motivazione. La classe astratta DialogDirector definisce l'interfaccia per i director.
class DialogDirector {
public:
virtual ~DialogDirector();
virtual void ShowDialog();
virtual void WidgetChanged(Widget*) = 0;
protected:
DialogDirector();
virtual void CreateWidgets() = 0;
};
Widget è la classe base astratta per i widget. Un widget conosce il suo direttore.
class Widget {
public:
Widget(DialogDirector*);
virtual void Changed();
virtual void HandleMouse(MouseEvent& event);
// ...
private:
DialogDirector* _director;
};
Changed chiama l'operazione WidgetChanged del regista. I widget chiamano WidgetChanged sul loro direttore per informarlo di un evento significativo.
void Widget::Changed () {
_director->WidgetChanged(this);
}
Sottoclassi di DialogDirector override WidgetChanged per influenzare i widget appropriati. Il widget passa un riferimento a se stesso come argomento a WidgetChanged per consentire al director di identificare il widget modificato. DialogDirector sottoclassi ridefiniscono il CreateWidgets puro virtuale per costruire i widget nella finestra di dialogo.
ListBox , EntryField e Button sono sottoclassi di Widget per elementi di interfaccia utente specializzati. ListBox fornisce un'operazione GetSelection per ottenere la selezione corrente e l'operazione EntryField SetText inserisce un nuovo testo nel campo.
class ListBox : public Widget {
public:
ListBox(DialogDirector*);
virtual const char* GetSelection();
virtual void SetList(List<char*>* 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 è un semplice widget che chiama Changed ogni volta che viene premuto. Questo viene fatto nella sua implementazione di 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();
}
La classe FontDialogDirector media tra i widget nella finestra di dialogo. FontDialogDirector è una sottoclasse di 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 tiene traccia dei widget visualizzati. Ridefinisce CreateWidgets per creare i widget e inizializzarne i riferimenti:
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 garantisce che i widget funzionino correttamente:
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
}
}
Quando voglio aggiungere un altro widget, devo affrontare 3 problemi:
- Devo aggiungere
MyNewWidgetclass. (non è un problema) - Devo modificare l'implementazione della classe
FontDialogDirectore aggiungereMyNewWidget* _myNewWidget;. - Aggiungi
_myNewWidget= new MyNewWidget(this); - Modifica l'implementazione del metodo
WidgetChangede aggiungielse if (theChangedWidget == _myNewWidget) //...ad essa.
C'è qualche soluzione che non ho nel codice, quando arriva un nuovo widget?
