Back Home Up Next


1 Purpose

2 Problem Description

3 Domain Definitions

4 Elisa Components


1  Purpose

Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

2  Problem Description

Object-oriented design encourages the distribution of behavior among objects. Such distribution can result in an object structure with many connections between objects; in the worst case, every object ends up knowing about every other.

Though partitioning a system into many objects generally enhances reusability, proliferating interconnections tend to reduce it again. Lots of interconnections make it less likely that an object can work without the support of others—the system acts as though it were monolithic. Moreover, it can be difficult to change the system's behavior in any significant way, since behavior is distributed among many objects. As a result, you may be forced to define many subclasses to customize the system's behavior.

As an example, consider the implementation of dialog boxes in a graphical user interface. A dialog box uses a window to present a collection of widgets such as buttons, menus, and entry fields, as shown here:

Often there are dependencies between the widgets in the dialog. For example, a button gets disabled when a certain entry field is empty. Selecting an entry in a list of choices called a list box might change the contents of an entry field. Conversely, typing text into the entry field might automatically select one or more corresponding entries in the list box. Once text appears in the entry field, other buttons may become enabled that let the user do something with the text, such as changing or deleting the thing to which it refers.

Different dialog boxes will have different dependencies between widgets. So even though dialogs display the same kinds of widgets, they can't simply reuse stock widget classes; they have to be customized to reflect dialog-specific dependencies. Customizing them individually by subclassing will be tedious, since many classes are involved.

You can avoid these problems by encapsulating collective behavior in a separate mediator object. A mediator is responsible for controlling and coordinating the interactions of a group of objects. The mediator serves as an intermediary that keeps objects in the group from referring to each other explicitly. The objects only know the mediator, thereby reducing the number of interconnections.

For example, FontDialogDirector can be the mediator between the widgets in a dialog box. A FontDialogDirector object knows the widgets in a dialog and coordinates their interaction. It acts as a hub of communication for widgets:

The following interaction diagram illustrates how the objects cooperate to handle a change in a list box's selection:

Here's the succession of events by which a list box's selection passes to an entry field:

  1. The list box tells its director that it's changed. 
  2. The director gets the selection from the list box. 
  3. The director passes the selection to the entry field. 
  4. Now that the entry field contains some text, the director enables button(s) for initiating an action (e.g., "demibold," "oblique").

Note how the director mediates between the list box and the entry field. Widgets communicate with each other only indirectly, through the director. They don't have to know about each other; all they know is the director. Furthermore, because the behavior is localized in one class, it can be changed or replaced by extending or replacing that class.

Here's how the FontDialogDirector abstraction can be integrated into a class library:

DialogDirector is an abstract class that defines the overall behavior of a dialog. Clients call the ShowDialog operation to display the dialog on the screen. CreateWidgets is an abstract operation for creating the widgets of a dialog. WidgetChanged is another abstract operation; widgets call it to inform their director that they have changed. DialogDirector subclasses override CreateWidgets to create the proper widgets, and they override WidgetChanged to handle the changes.


3  Domain Definitions

We will transform the top-level relations into a set of corresponding domain definitions:

DialogDirector = FontDialogDirector | ...

Widget = ListBox | EntryField | ...

The next step is to translate the domain definitions into a number of Elisa components. In addition, we will use skeletons of definitions as shown in the preceding domain relationships.


4  Elisa components 

Based on the domain definitions a set of related components are derived. The first component implements  a skeleton of the  DialogDirector domain.

component DialogDirectors;
type DialogDirector = category(Font

     ShowDialog(DialogDirector) -> nothing;

     CreateWidgets(DialogDirector) -> nothing;

     WidgetChanged(DialogDirector, Widget) -> nothing;

      . . .

            <<implementations of >>

     ShowDialog(FontDialogDirector: fontDialogDirector)= ShowDialog(fontDialogDirector); 

     CreateWidgets(FontDialogDirector: fontDialogDirector) = CreateWidgets(fontDialogDirector);

     WidgetChanged(FontDialogDirector: fontDialogDirector, Widget) = WidgetChanged(fontDialogDirector, Widget);

                           . . .

end component DialogDirectors;

The following component is a skeleton example of a FontDialogDirector component:


component FontDialogDirectors;
type FontDialogDirector;

     CreateFontDialogDirector( )  -> FontDialogDirector;

     ShowDialog(FontDialogDirector) -> nothing;

     CreateWidgets(FontDialogDirector) -> nothing;

     WidgetChanged(FontDialogDirector, Widget) -> nothing;

       . . .

            <<implementations of >>
     CreateFontDialogDirector( ) = FontDialogDirector:[ ... ];
     ShowDialog(FontDialogDirector) = ...;

     CreateWidgets(FontDialogDirector)= ...;

     WidgetChanged(FontDialogDirector, Widget)= ...;

        . . .

end component FontDialogDirectors;



The following component is a skeleton example of a Widget component:


component Widgets;
type Widget = category(ListBox, EntryField

     Changed(Widget) -> nothing;

      . . .

            <<implementations of >>

     Changed(widget)= WidgetChanged(DialogDirector, widget); 

                           . . .

end component Widgets;

The following component is a skeleton example of a ListBox component:


component ListBoxs;
type ListBox;

     CreateListBox( )  -> ListBox;

     GetSelection(ListBox) -> nothing;

       . . .

            <<implementations of >>
     CreateListBox( ) = ListBox:[ ... ];
     GetSelection(ListBox) = ...;

        . . .

end component ListBoxs;



The following component is a skeleton example of a EntryField component:


component EntryFields;
type EntryField;

     CreateEntryField( )  -> EntryField;

     SetText(EntryField) -> nothing;

       . . .

            <<implementations of >>
     CreateEntryField( ) = EntryField:[ ... ];
     SetText(EntryField) = ...;

        . . .

end component EntryFields;



Back Home Up Next

  Part 5: Design Patterns   Mediator


Home | Highlights of Elisa | Integrating Different Paradigms | Getting Started with Elisa | Demo's  | What is Domain Orientation | Bibliography | Copyright | News | Contact | Contents

Language Description:

Lexical Elements | Basic Data Types and Expressions | Definitions | Streams | Backtracking | Statements and Special Expressions | Arrays | Lists | Descriptors | Components | Collections | Generic Components | Terms | Categories | Types | Built-in Definitions | Higher-order Definitions | External Interfaces | Index 

Data Structures: Sequences | Examples involving Lists | Trees | Graphs | Searching State Spaces | Language Processing | Knowledge Representations
Domain Modeling:

Domain Modeling | Concepts | Domain Definitions | Domain Operations | Domain Implementations | Systems | Case study: an Order processing system | Case study: an Airport Support system | Domain Orientation versus Object Orientation

Design Patterns:

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


click tracking


Send me your comments


This page was last modified on 27-11-2012 16:52:48   

free hit counter