Преимущество шаблона Посредника

#design-patterns #language-agnostic #mediator

Вопрос:

Я читаю книгу Гофа. Не могли бы вы объяснить, пожалуйста, следующее преимущество:

Это ограничивает подклассы. Посредник локализует поведение, которое в противном случае было бы распределено между несколькими объектами. Для изменения этого поведения требуется только посредник подклассов; классы коллег могут быть повторно использованы как есть.

Означает ли это, что мы должны подклассировать Посредника или Конкретного Посредника? Можем ли мы иметь более одного конкретного посредника, которые наследуют один и тот же Посредник?

Ответ №1:

Книга написана в 1994 году или до этого, и в основном с примерами на C . Таким образом, он сильно использует наследование, отчасти потому, что C допускает множественное наследование, а отчасти потому, что в языке нет отдельной концепции интерфейса (например, Java или C#).

В начале книги говорится, что цель:

Отдавайте предпочтение композиции объектов, а не наследованию классов.

В книге подразумевается понимание того, что наследование может быть не лучшим механизмом для повторного использования.

Рассмотрим пример, приведенный для шаблона посредника: диалоговое окно шрифта. Без посредника ( FontDialogDirector ) ListBox ему нужно было бы напрямую знать об EntryField этом, чтобы сообщить ему об изменении его состояния.

Универсальное назначение ListBox должно быть полезно во многих контекстах, с или без сотрудничества EntryField . Таким образом, повторно ListBox используемый класс не может знать ни о каких «коллегах», потому что это сделало бы его не подлежащим повторному использованию.

Таким образом, без посредника вам потребуется подкласс ListBox , чтобы подключить его к an EntryField . В псевдо-C# это может выглядеть примерно так:

 public class FontList : ListBox
{
    public FontList(EntryField entryField)
    {
        EntryField = entryField;
    }

    public EntryField EntryField { get; }

    protected override void Changed()
    {
        EntryField.Text = this.Selection;
    }
}
 

Это очень специфический вид подклассов, который ограничивает шаблон посредника.

Означает ли это, что мы должны подклассировать Посредника или Конкретного Посредника?

Ни. Обратите внимание, что в подразделе Реализация описания шаблона указано:

Опуская абстрактный класс посредника. Нет необходимости определять абстрактный класс посредника, когда коллеги работают только с одним посредником. Абстрактная связь, обеспечиваемая классом Посредника, позволяет коллегам работать с различными подклассами посредника и наоборот.

Mediator Класс выступает в качестве центральной точки соприкосновения для коллег. Если есть только один Посредник, он может быть конкретным. Отличительный момент заключается в том, как вы распространяете изменения. В примере каждый Widget из них распространяет изменения на свои DialogDirector , как это:

 _director->WidgetChanged(this);
 

Мы можем себе представить, что Widget это должен быть многоразовый класс, поэтому мы хотели бы отделить его от любого конкретного посредника. Здесь предполагается, что их может быть несколько.

С другой стороны, если у вас есть специализированный набор коллег, которые не могут использоваться повторно, они могут общаться через конкретного посредника. Если повторное использование в этой ситуации не требуется, Посредник не обязательно должен быть абстрактным классом.

Комментарии:

1. в части реализации (в книге) не могли бы вы, пожалуйста, объяснить, где я должен использовать эту void Widget::Changed () { _director->WidgetChanged(this); } часть? В основном? (я не силен в c )

2. @MichaelMaier Я скопировал эту строку кода прямо из раздела Примеров кода книги, в котором объясняется контекст. Прошло более 20 лет с тех пор, как я делал что-либо на C , поэтому я не уверен, но, возможно, это переопределяет метод Widget класса Changed , который, я думаю, мы должны рассматривать как обработчик событий.