الگوی میانجی

در مهندسی نرم‌افزار الگوی میانجی تعریف یک شی است که روابط مجموعه‌ای از اشیاء را تهیه و تعیین می‌کند. این الگو به خاطر آن که می‌تواند رفتار برنامه را در حین اجرا تغییر دهد، به عنوان یک الگوی رفتاری شناخته می‌شود.

برنامه‌ها معمولاً از تعداد زیادی کلاس تشکیل می‌شوند. در نتیجه منطق برنامه و محاسبات آن بین این کلاس‌ها توزیع می‌شوند. اما، در حالی که در مرحله نگهداری یا بازسازی کد تعداد کلاس‌ها بیشتر می‌شوند، مشکل ارتباط بین این کلاس‌ها ممکن است پیپیده‌تر شود. این باعث دشواری بیشتر در خواندن و حفظ کد می‌شود. همچنین تغییر برنامه، به خاطر آن که هر تغییر باعث تغییر تعداد زیادی از کلاس‌های دیگر می‌شود، سخت‌تر خواهد شد.

با کمک الگوی میانجی، ارتباط بین اشیاء در یک شیء میانجی‌گر محدود می‌شود. در نتیجه اشیاء بجای این که مستقیم با یکدیگر ارتباط برقرار کنند، ارتباطات خود را از طریق میانجی‌گر انجام می‌دهند. این باعث کاهش ارتباطات بین اشیاء شده و در نتیجه جفتگری (coupling) کاهش می‌یابد.

با استفاده از الگوی میانجی، تغییرات بر روی اشیاء داخل مجموعه دیگر منشتر شونده نخواهند بود و اصطلاحاً  shotgun surgery از بین می‌رود. اما از طرف دیگر امکان تبدیل میانجی به کلاس خدا و ایجاد گلوگاه در سیستم وجود دارد.

تعریف 

تعریف الگوی میانجی: «یک شیء است که ارتباطات بین دسته‌ای از اشیاء را تهیه و تعیین می‌کند». باعث کاهش جفتگری (coupling) می‌شود چرا که جلوی اشیاء را برای ارتباط مستقیم با یکدیگر می‌گیرد. کلاس‌های مشتری می‌توانند از میانجی برای فرستادن پیغام به دیگر کلاس‌های مشتری استفاده کنند، و جواب خود را از طریق آن دریافت کنند.

شرکت‌کنندگان در الگو 
Mediator - تعریف رابط برای ارتباط بین اشیاء مرتبط (همکار)

ConcreteMediator - پیاده‌سازی میانجی و رابط کاربری و جزئیات ارتباطات اشیاء مرتبط (همکار) را مشخص می‌کند. از ارتباطات همکاری آگاه است و هدف آن‌ها را در ارتباطات داخلی می‌داند.

ConcreteColleague - توسط میانجی با دیگر همکارانش ارتباط برقرار می‌کند.

مثال

#C 
الگوی میانجی مطمئن می‌شود که قسمت‌های مختلف (components) آزادانه ارتباط برقرار کنند، به طوری که مستقیم یکدیگر را صدا نکنند؛ و به جای آن همیشه از یک واسطه‌گر برای انجام این اهداف استفاده کنند. همان طور که می‌بینید، واسطه‌گر همه بخش‌ها را در خود ذخیره کرده‌است و در هنگام نیاز توابع آن‌ها را فراخوانی می‌کند.public interface IComponent
{
    void SetState(object state);
}

public class Component1 : IComponent
{
    public void SetState(object state)
    {
        throw new NotImplementedException();
    }
}

public class Component2 : IComponent
{
    public void SetState(object state)
    {
        throw new NotImplementedException();
    }
}

// Mediates the common tasks
public class Mediator
{
    public IComponent Component1 { get; set; }
    public IComponent Component2 { get; set; }

    public void ChangeState(object state)
    {
        this.Component1.SetState(state);
        this.Component2.SetState(state);
    }
}یک اتاق گفتگو (چت) می‌تواند از یک الگوی میانجی استفاده کند، بدین صورت که هر کاربری (مشتری) وقتی که دیگر کاربران کاری (در اتاق چت منظور فرستادن پیغام است) انجام دهند مطلع می‌شود.
در واقعیت استفاده از الگوی میانجی در اتاق گفتگو تنها در صورتی می‌تواند عملی باشد که توسط یک کنترل از راه دور استفاده شود. استفاده از سوکت‌های شبکه، امکان فراخوانی نمایندگان را نمی‌دهد. (فراخوانی: عملیات دریافت پیغام توسط افراد عضو شده در یک کلاس میانجی)

جاوا 
در این مثال شیء میانجی، کنترل وضعیت سه دکمه همکار را بر عهده می‌گیرد، و برای آن سه تابع book و view و search را که وضعیت دکمه‌ها را تنظیم می‌کند دارد. این توابع توسط دکمه در هنگام فعال شد (با دستور execute در هر کدام) فراخوانی می‌شوند.

از این رو الگوی ارتباط به این صورت است که هر عضو (در این‌جا دکمه) با فعالیت خود را با میانجی در میان گذاشته و میانجی عملیات لازم را در اختیار اعضای دیگر قرار می‌دهد.import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

//Colleague interface
interface Command {
    void execute();
}

//Abstract Mediator
interface Mediator {
    void book();
    void view();
    void search();
    void registerView(BtnView v);
    void registerSearch(BtnSearch s);
    void registerBook(BtnBook b);
    void registerDisplay(LblDisplay d);
}

//Concrete mediator
class ParticipantMediator implements Mediator {

    BtnView btnView;
    BtnSearch btnSearch;
    BtnBook btnBook;
    LblDisplay show;

    //....
    public void registerView(BtnView v) {
        btnView = v;
    }

    public void registerSearch(BtnSearch s) {
        btnSearch = s;
    }

    public void registerBook(BtnBook b) {
        btnBook = b;
    }

    public void registerDisplay(LblDisplay d) {
        show = d;
    }

    public void book() {
        btnBook.setEnabled(false);
        btnView.setEnabled(true);
        btnSearch.setEnabled(true);
        show.setText("booking...");
    }

    public void view() {
        btnView.setEnabled(false);
        btnSearch.setEnabled(true);
        btnBook.setEnabled(true);
        show.setText("viewing...");
    }

    public void search() {
        btnSearch.setEnabled(false);
        btnView.setEnabled(true);
        btnBook.setEnabled(true);
        show.setText("searching...");
    }

}

//A concrete colleague
class BtnView extends JButton implements Command {

    Mediator med;

    BtnView(ActionListener al, Mediator m) {
        super("View");
        addActionListener(al);
        med = m;
        med.registerView(this);
    }

    public void execute() {
        med.view();
    }

}

//A concrete colleague
class BtnSearch extends JButton implements Command {

    Mediator med;

    BtnSearch(ActionListener al, Mediator m) {
        super("Search");
        addActionListener(al);
        med = m;
        med.registerSearch(this);
    }

    public void execute() {
        med.search();
    }

}

//A concrete colleague
class BtnBook extends JButton implements Command {

    Mediator med;

    BtnBook(ActionListener al, Mediator m) {
        super("Book");
        addActionListener(al);
        med = m;
        med.registerBook(this);
    }

    public void execute() {
        med.book();
    }

}

class LblDisplay extends JLabel {

    Mediator med;

    LblDisplay(Mediator m) {
        super("Just start...");
        med = m;
        med.registerDisplay(this);
        setFont(new Font("Arial", Font.BOLD, 24));
    }

}

class MediatorDemo extends JFrame implements ActionListener {

    Mediator med = new ParticipantMediator();

    MediatorDemo() {
        JPanel p = new JPanel();
        p.add(new BtnView(this, med));
        p.add(new BtnBook(this, med));
        p.add(new BtnSearch(this, med));
        getContentPane().add(new LblDisplay(med), "North");
        getContentPane().add(p, "South");
        setSize(400, 200);
        setVisible(true);
    }

    public void actionPerformed(ActionEvent ae) {
        Command comd = (Command) ae.getSource();
        comd.execute();
    }

    public static void main(String[] args) {
        new MediatorDemo();
    }

}

جستارهای وابسته 
 الگوهای طراحی
 میانجیگر اطلاعات
 الگوهای طراحی، کتابی که باعث شروع مطالعات الگوهای طراحی در مهندسی کامپیوتر شد.
 الگوی طراحی (علوم کامپیوتر)یک راه حل استاندارد برای مشکلات رایج در طراحی نرم‌افزار

منابع

پیوند به بیرون 
 الگوی اسطه طراحی
 مثال پیاده‌سازی الگوی یانجی‌گر C++11
 استفاده از الگوی میانجی‌گر را پیشنهاد می‌کنید ؟ - Stack Overflow

الگوهای طراحی نرم‌افزار