结构

中介者模式

说明

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.

包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用,从而使它们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用,保证这些作用可以彼此独立的变化。

适用条件

一组对象以定义良好但是复杂的方式进行通信, 之间产生的相互依赖关系结构混乱且难以理解, 一个对象引用其他很多对象, 并且直接与这些对象通信, 导致难以复用该对象。

实现

public interface IColleague {

   void Execute();
}

public interface IMediator {

   void Book();

   void View();

   void Search();

   void RegisterView(ViewButton viewButton);

   void RegisterSearch(SearchButton searchButton);

   void RegisterBook(BookButton bookButton);

   void RegisterDisplay(DisplayLabel displayLabel);

}

class Mediator : IMediator {

   private ViewButton _viewButton;
   private SearchButton _searchButton;
   private BookButton _bookButton;
   private DisplayLabel _displayLabel;
   
   public void Book() {
      this._bookButton.IsEnabled = false;
      this._viewButton.IsEnabled = true;
      this._searchButton.IsEnabled = true;
      this._displayLabel.Content = "Booking ...";
   }

   public void View() {
      this._bookButton.IsEnabled = true;
      this._viewButton.IsEnabled = false;
      this._searchButton.IsEnabled = true;
      this._displayLabel.Content = "Viewing ...";
   }

   public void Search() {
      this._bookButton.IsEnabled = true;
      this._viewButton.IsEnabled = true;
      this._searchButton.IsEnabled = false;
      this._displayLabel.Content = "Searching ...";
   }

   public void RegisterView(ViewButton viewButton) {
      this._viewButton = viewButton;
   }

   public void RegisterSearch(SearchButton searchButton) {
      this._searchButton = searchButton;
   }

   public void RegisterBook(BookButton bookButton) {
      this._bookButton = bookButton;
   }

   public void RegisterDisplay(DisplayLabel displayLabel) {
      this._displayLabel = displayLabel;
   }
}

public class BookButton : Button, IColleague {
   
   private readonly IMediator _mediator;

   public BookButton(IMediator mediator) {
      this.Content = "Book";
      this._mediator = mediator;
      this._mediator.RegisterBook(this);
   }

   public void Execute() {
      this._mediator.Book();
   }
}

public class SearchButton : Button, IColleague {

   private readonly IMediator _mediator;

   public SearchButton(IMediator mediator) {
      this.Content = "Search";
      this._mediator = mediator;
      this._mediator.RegisterSearch(this);
   }

   public void Execute() {
      this._mediator.Search();
   }
}

public class ViewButton : Button, IColleague {

   private readonly IMediator _mediator;

   public ViewButton(IMediator mediator) {
      this.Content = "View";
      this._mediator = mediator;
      this._mediator.RegisterView(this);
   }

   public void Execute() {
      this._mediator.View();
   }
}

public class DisplayLabel : Label {

   private readonly IMediator _mediator;

   public DisplayLabel(IMediator mediator) {
      this.Content = "Starting ...";
      this.FontSize = 24;
      //this.FontWeight = new FontWeight();
      this._mediator = mediator;
      this._mediator.RegisterDisplay(this);
   }
}

class MediatorDemo : Window {

   private readonly IMediator _mediator = new Mediator();

   public MediatorDemo() {

      var rootView = new Grid();
      rootView.RowDefinitions.Add(new RowDefinition());
      rootView.RowDefinitions.Add(new RowDefinition());
      rootView.ColumnDefinitions.Add(new ColumnDefinition());
      rootView.ColumnDefinitions.Add(new ColumnDefinition());
      rootView.ColumnDefinitions.Add(new ColumnDefinition());

      var viewButton = new ViewButton(this._mediator);
      viewButton.Click += this.OnViewClick;
      Grid.SetColumn(viewButton, 0);
      Grid.SetRow(viewButton, 0);
      rootView.Children.Add(viewButton);

      var bookButton = new BookButton(this._mediator);
      bookButton.Click += this.OnViewClick;
      Grid.SetColumn(bookButton, 1);
      Grid.SetRow(bookButton, 0);
      rootView.Children.Add(bookButton);

      var searchButton = new SearchButton(this._mediator);
      searchButton.Click += this.OnViewClick;
      Grid.SetColumn(searchButton, 2);
      Grid.SetRow(searchButton, 0);
      rootView.Children.Add(searchButton);


      var displayLabel = new DisplayLabel(this._mediator);
      Grid.SetColumn(displayLabel, 0);
      Grid.SetRow(displayLabel, 1);
      Grid.SetColumnSpan(displayLabel, 3);
      rootView.Children.Add(displayLabel);

      this.Content = rootView;

      this.Width = 400;
      this.Height = 200;
      this.Title = "Mediator Demo";
   }

   private void OnViewClick(object sender, RoutedEventArgs routedEventArgs) {
      var colleague = (IColleague)sender;
      colleague.Execute();
   }

   [STAThread]
   static void Main(string[] args) {
      var app = new Application();
      app.Startup += AppOnStartup;
      app.Run();
   }

   private static void AppOnStartup(object sender, StartupEventArgs startupEventArgs) {
      Application.Current.MainWindow = new MediatorDemo();
      Application.Current.MainWindow.Show();
   }

}

中介者模式也是最为常见的设计模式之一, 不管是 WinForm, WebForm 还是 WPF , 均可以考虑采用中介者模式。