Search code examples
design-patternslanguage-agnosticmediator

Mediator Pattern Advantage


Im reading the book of GoF. Could you please explain the following Advantage:

It limits subclassing. A mediator localizes behavior that otherwise would be distributed among several objects. Changing this behavior requires subclassing Mediator only; Colleague classes can be reused as is.

Is it meant that we should subclass the Mediator or the ConcreteMediator? Can we have more than one ConcreteMediators that inherit form the same Mediator?


Solution

  • The book is written in or before 1994, and mainly with examples in C++. Thus, it uses inheritance heavily, partly because C++ allows multiple inheritance, and partly because the language has no separate concept of an interface (like Java or C#).

    Early in the book, it states as a goal:

    Favor object composition over class inheritance.

    Implicit in the book is the understanding that inheritance may not be the best mechanism for reuse.

    Consider the example given for the Mediator pattern: the font dialog. Without a Mediator (FontDialogDirector) the ListBox would need to directly know about the EntryField in order to update it about its state change.

    A general-purpose ListBox should be useful in many contexts, with or without a collaborating EntryField. Thus, a reusable ListBox class can't know about any 'colleagues', because that would make it non-reusable.

    Thus, without a Mediator, you'd need to subclass ListBox to connect it to an EntryField. In pseudo-C# it might look something like this:

    public class FontList : ListBox
    {
        public FontList(EntryField entryField)
        {
            EntryField = entryField;
        }
    
        public EntryField EntryField { get; }
    
        protected override void Changed()
        {
            EntryField.Text = this.Selection;
        }
    }
    

    This is the very specific kind of subclassing that the Mediator pattern limits.

    Is it meant that we should subclass the Mediator or the ConcreteMediator?

    Neither. Notice that the pattern description's Implementation subsection states:

    Omitting the abstract Mediator class. There's no need to define an abstract Mediator class when colleagues work with only one mediator. The abstract coupling that the Mediator class provides lets colleagues work with different Mediator subclasses and vice versa.

    The Mediator class acts as a central point of contact for Colleagues. If there's only one Mediator it can be concrete. The distinguishing point is how you propagate change. In the example, each Widget propagates change to its DialogDirector like this:

    _director->WidgetChanged(this);
    

    We can imagine that Widget ought to be a reusable class, so we'd want to decouple it from any concrete Mediator. Here, the assumption is that there might be more than one.

    If, on the other hand, you have a specialised set of Colleagues that are not reusable, they can communicate via a concrete Mediator. If reuse isn't a requirement in that situation, the Mediator doesn't have to be an abstract class.