23. Facade and Mediator

image

© Jennifer M. Kohnke

Symbolism erects a facade of respectability to hide the indecency of dreams.

—Mason Cooley

The two patterns discussed in this chapter have a common purpose: imposing some kind of policy on another group of objects. FACADE imposes policy from above; MEDIATOR, from below. The use of FACADE is visible and constraining; that of MEDIATOR, invisible and enabling.

Facade

The FACADE pattern is used when you want to provide a simple and specific interface onto a group of objects that have a complex and general interface. Consider, for example, DB.cs in Listing 34-9. This class imposes a very simple interface, specific to ProductData, on the complex and general interfaces of the classes within the System.Data namespace. Figure 23-1 shows the structure.

Figure 23-1. The DB FACADE

image

Notice that the DB class protects the Application from needing to know the intimacies of the System.Data namespace. The class hides all the generality and complexity of System.Data behind a very simple and specific interface.

A FACADE like DB imposes a lot of policy on the usage of System.Data, knowing how to initialize and close the database connection, translate the members of ProductData into database fields and back, and build the appropriate queries and commands to manipulate the database. All that complexity is hidden from users. From the point of view of the Application, System.Data does not exist; it is hidden behind the FACADE.

The use of the FACADE pattern implies that the developers have adopted the convention that all database calls must go through DB. If any part of the Application code goes straight to System.Data rather than through the FACADE, that convention is violated. As such, the FACADE imposes its polices on the application. By convention, DB has become the sole broker of the facilities of System.Data.

FACADE can be used to hide any aspect of a program. However, using FACADE to hide the database has become so common, the pattern is also known as TABLE DATA GATEWAY.

Mediator

The MEDIATOR pattern also imposes policy. However, whereas FACADE imposes its policy in a visible and constraining way, MEDIATOR imposes its policies in a hidden and unconstraining way. For example, the QuickEntryMediator class in Listing 23-1 sits quietly behind the scenes and binds a text-entry field to a list. When you type in the text-entry field, the first list element that matches what you have typed is highlighted. This lets you type abbreviations and quickly select a list item.


Listing 23-1. QuickEntryMediator.cs

using System;
using System.Windows.Forms;

/// <summary>
/// QuickEntryMediator. This class takes a TextBox and a
/// ListBox. It assumes that the user will type
/// characters into the TextBox that are prefixes of
/// entries in the ListBox. It automatically selects the
/// first item in the ListBox that matches the current
/// prefix in the TextBox.
///
/// If the TextField is null, or the prefix does not
/// match any element in the ListBox, then the ListBox
/// selection is cleared.
///
/// There are no methods to call for this object. You
/// simply create it, and forget it. (But don't let it
/// be garbage collected...)
///
/// Example:
///
/// TextBox t = new TextBox();
/// ListBox l = new ListBox();
///
/// QuickEntryMediator qem = new QuickEntryMediator(t,l);
///  // that's all folks.
///
/// Originally written in Java
/// by Robert C. Martin, Robert S. Koss
/// on 30 Jun, 1999 2113 (SLAC)
/// Translated to C# by Micah Martin
/// on May 23, 2005 (On the Train)
/// </summary>
public class QuickEntryMediator
{
  private TextBox itsTextBox;
  private ListBox itsList;

  public QuickEntryMediator(TextBox t, ListBox l)
  {
    itsTextBox = t;
    itsList = l;

    itsTextBox.TextChanged += new EventHandler(TextFieldChanged);
  }
  private void
    TextFieldChanged(object source, EventArgs args)
  {
    string prefix = itsTextBox.Text;

    if (prefix.Length == 0)
    {
      itsList.ClearSelected();
      return;
    }

    ListBox.ObjectCollection listItems = itsList.Items;
    bool found = false;
    for (int i = 0; found == false &&
              i < listItems.Count; i++)
    {
      Object o = listItems[i];
      String s = o.ToString();
      if (s.StartsWith(prefix))
      {
        itsList.SetSelected(i, true);
        found = true;
      }
    }
    if (!found)
    {
      itsList.ClearSelected();
    }
  }
}


The structure of the QuickEntryMediator is shown in Figure 23-2. An instance of QuickEntryMediator is constructed with a ListBox and a TextBox. The Quick-EntryMediator registers an EventHandler with the TextBox. This EventHandler invokes the TextFieldChanged method whenever there is a change in the text. This method then finds a ListBox element that is prefixed by the text and selects it.

Figure 23-2. QuickEntryMediator

image

The users of the ListBox and TextField have no idea that this MEDIATOR exists. It quietly sits there, imposing its policy on those objects without their permission or knowledge.

Conclusion

Imposing policy can be done from above, using FACADE, if that policy needs to be big and visible. On the other hand, if subtlety and discretion are needed, MEDIATOR may be the more appropriate choice. FACADEs are usually the focal point of a convention. Everyone agrees to use the FACADE instead of the objects beneath it. MEDIATOR, on the other hand, is hidden from the users. Its policy is a fait accompli rather than a matter of convention.

Bibliography

[Fowler03] Martin Fowler, Patterns of Enterprise Application Architecture, Addison-Wesley, 2003.

[GOF95] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, 1995.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.97.61