این سایت برای ie9 طراحی نشده است

لطفا دستگاه خود را بچرخانید.

الگوی طراحی – Mediator

۲۴ اردیبهشت ۱۳۹۶ حسین صداقت
بدون دیدگاه

به نام خدا

همانطور که در مطلب قبلی  اشاره کردیم در این مطلب می خواهیم الگوی طراحی Mediator را با هم بررسی کنیم.

الگوی طراحی Mediator همانطور که اسم از آن نیز می توان حدس زد وظیفه ی یک واسط و مدیریت کردن ارتباطات بین اشیا را بر عهده دارد.نمودار UML این الگو به صورت زیر می باشد:Mediator UML Diagram

نقش های شرکت کننده در این الگوی طراحی موارد زیر هستند:

  • Mediator : یک اینترفیس است برای ارتاباط بین اشیایی که با هم کار می کنند.
  • ConcreteMediator : ارتباط بین اشیا در این کلاس تعریف می شود و همچنین اشیایی که قرار است با هم در ارتباط باشند را می شناسد.
  • ColleagueClasses : همان اشیایی می باشند که با هم در ارتباط هستند و Mediator را می شناسند.

سناریوی زیر را در نظر بگیرید:

” فرض کنید ما میخواهیم یک خانه هوشمند با این مشخصات  داشته باشیم .صبح وقتی که ساعت جهت بیدار شدن زنگ می خورد با زدن دکمه Snooze می خواهیم قهوه  شروع به دم شدن بکند.همینطور میخواهیم که آخر هفته ها قهوه از برنامه خارج شود و همنیطور آب پاش های باغچه ۱۵ دقیقه قبل از گرم شدن حمام و روشن دوش خاموش شوند.همینطور ساعت در روز هایی که قرار است زباله از خانه خارج شود زودتر زنگ بخورد.” اگر هر کدام از وسایل را یک شی در نظر بگیریم شکل ارتباطات بین اشیا و متد های هر کلاس به صورت زیر می شود:

 

 

 

 

Mediator

همانطور که در شکل هم پیداست پیاده سازی و هندل کردن رابطه ی بین اشیا در حالتی که اشیا قرار است مستقیما هم دیگر را Call کنند واقعا کثیف و پیچیده میشود.حال فرض کنید ما یک شی واسطی داشته باشیم که رابطه این اشیا را برای ما مدیریت کند:

Mediator2

همانطور که در شکل هم مشهود هستش Mediator همان شی واسط ما می باشد که وظیفه مدیریت بین روابط اشیا را در بر عهده میگیرد و سبب می شود که که در پیاده سازی و همینطور سناریو های پیچیده با مشکل مواجه نشویم.همچنین این الگوی طراحی سبب می شود که دیگر اشیا به طور مستقیم با هم ارتباط نداشته باشند.

 

مثال ۲:فرض کنید ما یک Chatroom ساده می خواهیم پیاده سازی کنیم که در آن کاربرانی که ثبت نام می کنند میتوانند به هم پیغام دهند:

اول ازهمه اینترفیس Mediator را پیاده سازی می کنیم:

abstract class AbstractChatroom
{
  public abstract void Register(Participant participant);
  public abstract void Send(
    string from, string to, string message);
}

 

در این اینترفیس ساختار دو متد در آن تعریف شده است۱-Register که وظیفه ثبت نام شکرت کنندگان در این چت روم را دارد.۲-Send که وظیفه ارسال پیام بین کاربران (اشیا) را بر عهده دارد.

 

حال به سراغ  پیاده سازی کلاس Chatroom که همان نقش Mediator را دارد می رویم.این کلاس اینترفیس Mediator را پیاده سازی می کند:

class Chatroom : AbstractChatroom
{
  private Dictionary<string,Participant> _participants = 
    new Dictionary<string,Participant>();
 
  public override void Register(Participant participant)
  {
    if (!_participants.ContainsValue(participant))
    {
      _participants[participant.Name] = participant;
    }
 
    participant.Chatroom = this;
  }
 
  public override void Send(
    string from, string to, string message)
  {
    Participant participant = _participants[to];
 
    if (participant != null)
    {
      participant.Receive(from, message);
    }
  }
}

 

در کد بالا اول از همه ما یک فیلد از نوع Dictionary داریم.وظیفه این فیلد ذخیره اشیا شرکت کننده در این ارتباط می باشد و ساختار آن Key,Value می باشد.یعنی بر اساس Key که همان نام شی ذخیره شده می باشد ،خود شی را در اختیار ما می گذارد.

وظیفه متد Register اضافه کردن یک شی  به مجموعه اشیای شرکت کننده در این Chatroom می باشد.همچنین ما در این متد Mediator را از طریق مقدار دهی فیلد Chatroom    شی در حال رجیستر شدن، به شی می شناسونیم!

متد بعدی متد Send است که با  استفاده از متد Receive اشیای شرکت کننده در Chatroom پیغام را به شی مقصد می رساند.

 

کلاس یعدی که ما به سراغ پیاده سازی آن می رویم کلاس Participant می باشد.این کلاس در حقیقت نقش کلاس AbstractColleague را بازی میکند.یعنی اشیایی می توانند در Chatroom شرکت کنند که از این کلاس ارث ببرند.

/// <summary>
/// The 'AbstractColleague' class
/// </summary>
class Participant
{
  private Chatroom _chatroom;
  private string _name;
 
  // Constructor
  public Participant(string name)
  {
    this._name = name;
  }
 
  // Gets participant name
  public string Name
  {
    get { return _name; }
  }
 
  // Gets chatroom
  public Chatroom Chatroom
  {
    set { _chatroom = value; }
    get { return _chatroom; }
  }
 
  // Sends message to given participant
  public void Send(string to, string message)
  {
    _chatroom.Send(_name, to, message);
  }
 
  // Receives message from given participant
  public virtual void Receive(
    string from, string message)
  {
    Console.WriteLine("{0} to {1}: '{2}'",
      from, Name, message);
  }
}

ساختار این کلاس هم همانطور که می بینیم دارای یک فیلد نام می باشد که در Constructor مقدار دهی می شود.همچنین دارای یک Property از نوع Chatroom می باشد .چون همه اشیا شرکت کننده باید Mediator که در اینجا همان کلاس Chatroom  ما می باشد را بشناسند و از آن استفاده کنند و این شناسایی از طریق مقدار دهی این Proeprty در هنگام Register شدن یک شی در متد Register کلاس Chatroom انجام می شود.

participant.Chatroom = this;

 

همچنین این کلاس دارای دو متد  Send و Receive می باشد که متد Send با استفاده از کلاس Chatroom به ارسال پیام به مقصد می پردازد و متد Receive وظیفه دریافت پیام های ارسالی به یک شی را دارد.

حالا به سراغ پیاده سازی کلاس ها و اشیای شرکت کننده اصلی در این Chatroom می پردازیم.در این مثال ما دو نوع کلاس متفاوت شرکت کننده در Chat داریم.که اسم کلاس اول را GroupA و اسم کلاس دوم را GroupB می گذاریم.این دو کلاس هر دو باید از کلاس Participant ارث ببرند:

class GroupA: Participant
{
  // Constructor
  public GroupA(string name)
    : base(name)
  {
  }
 
  public override void Receive(string from, string message)
  {
    Console.Write("To a GroupA: ");
    base.Receive(from, message);
  }
}
 
/// <summary>
/// A 'ConcreteColleague' class
/// </summary>
class GroupB: Participant
{
  // Constructor
  public GroupB(string name)
    : base(name)
  {
  }
 
  public override void Receive(string from, string message)
  {
    Console.Write("To a GroupB: ");
    base.Receive(from, message);
  }
}

 

در Constructor هر دو کلاس با فرخوانی Constructor کلاس پدر یعنی کلاس Participant نام آن ها ست می شود.همچنین متد Receive کلاس پدر نیز override شده تا بر اساس نوع هر کلاس ، متد Receive پیاده سازی شود.

حال به صورت میزاریم میتوانیم جهت ارسال پیام عمل کینم:

class MainApp
{
  /// <summary>
  /// Entry point into console application.
  /// </summary>
  static void Main()
  {
    // Create chatroom
    Chatroom chatroom = new Chatroom();
 
    // Create participants and register them
    Participant George = new GroupA("George");
    Participant Paul = new GroupA("Paul");
    Participant Ringo = new GroupA("Ringo");
    Participant John = new GroupA("John");
    Participant Yoko = new GroupB("Yoko");
 
    chatroom.Register(George);
    chatroom.Register(Paul);
    chatroom.Register(Ringo);
    chatroom.Register(John);
    chatroom.Register(Yoko);
 
    // Chatting participants
    Yoko.Send("John", "Hi John!");
    Paul.Send("Ringo", "All you need is love");
    Ringo.Send("George", "My sweet Lord");
    Paul.Send("John", "Can't buy me love");
    John.Send("Yoko", "My sweet love");
 
    // Wait for user
    Console.ReadKey();
  }
}

ان شاءلله در مطلب بعدی با یکدیگر Memento را بررسی می کنیم.

 

منابع این مطلب :

۱- http://www.dofactory.com/net/design-patterns

۲- کتاب head first design patterns