MATIN MOLKARA
SERIES: JavaScript — PART 86 OF 108

86- آموزش جاوااسکریپت | Mediator Pattern

در این بخش با Mediator Pattern در JavaScript آشنا می‌شویم؛ الگویی برای مدیریت ارتباط بین آبجکت‌ها از طریق یک واسطه مرکزی. همچنین با مثال عملی اتاق گفت‌وگو، نحوه ارسال پیام خصوصی و عمومی را بررسی می‌کنیم.

در این بخش، الگوی Mediator Pattern را بررسی می‌کنیم. این الگو یکی از Behavioral Patternها است و هدف آن، مدیریت ارتباط بین چند آبجکت از طریق یک واسطه مرکزی است.

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

Mediator Pattern چیست؟

در Mediator Pattern، یک آبجکت مرکزی به نام Mediator مسئول هماهنگی ارتباط بین چند آبجکت دیگر است. این آبجکت‌های دیگر معمولاً Colleague نامیده می‌شوند.

در این الگو:

  • Mediator مسئول برقراری ارتباط است
  • Colleagueها به‌جای ارتباط مستقیم با هم، از طریق Mediator پیام ردوبدل می‌کنند
  • وابستگی بین اجزا کمتر می‌شود
  • تغییر یا توسعه سیستم آسان‌تر خواهد شد

مثال کاربردی: اتاق گفت‌وگو

یکی از بهترین مثال‌ها برای Mediator Pattern، یک Chat Room یا اتاق گفت‌وگو است.

در این مثال:

  • هر کاربر یک colleague است
  • اتاق گفت‌وگو نقش mediator را دارد
  • کاربران می‌توانند:
    • به یک کاربر خاص پیام بدهند
    • یا پیام را برای همه کاربران ارسال کنند

ساختار کلی مثال

در این پیاده‌سازی، دو سازنده اصلی داریم:

  • User
  • Chatroom

کلاس User نماینده کاربران است و Chatroom نقش واسطه را بر عهده دارد.

تعریف سازنده User

ابتدا سازنده مربوط به کاربر را تعریف می‌کنیم:

const User = function (name) {
  this.name = name;
  this.chatroom = null;
};

در اینجا:

  • name نام کاربر را نگه می‌دارد
  • chatroom در ابتدا null است، چون کاربر هنوز در هیچ اتاقی ثبت نشده است

تعریف سازنده Chatroom

اکنون سازنده اتاق گفت‌وگو را می‌سازیم:

const Chatroom = function () {
  this.users = {};
};

در اینجا، ویژگی users یک آبجکت خالی است که لیست کاربران ثبت‌شده در اتاق را نگه می‌دارد.

تعریف متدهای User

برای کاربران دو متد اصلی تعریف می‌کنیم:

  • send
  • receive
User.prototype = {
  send: function (message, to) {
    this.chatroom.send(message, this, to);
  },

  receive: function (message, from) {
    console.log(`${from.name} to ${this.name}: ${message}`);
  }
};

بررسی متدهای User

متد send

این متد مستقیماً به کاربر دیگر پیام نمی‌فرستد.
به‌جای آن، پیام را به chatroom می‌دهد تا mediator تصمیم بگیرد پیام باید به چه کسی برسد.

send: function (message, to) {
  this.chatroom.send(message, this, to);
}

متد receive

این متد زمانی اجرا می‌شود که کاربر پیامی دریافت کند:

receive: function (message, from) {
  console.log(`${from.name} to ${this.name}: ${message}`);
}

تعریف متدهای Chatroom

اکنون نوبت به تعریف منطق mediator می‌رسد. اتاق گفت‌وگو باید بتواند:

  • کاربران را ثبت کند
  • پیام خصوصی ارسال کند
  • پیام عمومی برای همه کاربران بفرستد
Chatroom.prototype = {
  register: function (user) {
    this.users[user.name] = user;
    user.chatroom = this;
  },

  send: function (message, from, to) {
    if (to) {
      to.receive(message, from);
    } else {
      for (let key in this.users) {
        if (this.users[key] !== from) {
          this.users[key].receive(message, from);
        }
      }
    }
  }
};

بررسی متدهای Chatroom

متد register

این متد یک کاربر را در اتاق ثبت می‌کند:

register: function (user) {
  this.users[user.name] = user;
  user.chatroom = this;
}

در این متد:

  • کاربر با کلید name در لیست کاربران ذخیره می‌شود
  • مرجع chatroom کاربر به اتاق فعلی اختصاص داده می‌شود

متد send

این متد مسئول ارسال پیام است:

send: function (message, from, to) {
  if (to) {
    to.receive(message, from);
  } else {
    for (let key in this.users) {
      if (this.users[key] !== from) {
        this.users[key].receive(message, from);
      }
    }
  }
}

منطق این متد به دو حالت تقسیم می‌شود:

1. ارسال پیام خصوصی

اگر مقدار to وجود داشته باشد، پیام فقط به همان کاربر ارسال می‌شود:

to.receive(message, from);

2. ارسال پیام عمومی

اگر to مشخص نشده باشد، پیام برای همه کاربران اتاق ارسال می‌شود، به‌جز فرستنده:

for (let key in this.users) {
  if (this.users[key] !== from) {
    this.users[key].receive(message, from);
  }
}

ساخت کاربران و اتاق گفت‌وگو

اکنون چند کاربر و یک chatroom می‌سازیم:

const brad = new User('Brad');
const jeff = new User('Jeff');
const sarah = new User('Sarah');

const chatroom = new Chatroom();

ثبت کاربران در Chatroom

قبل از ارسال پیام، کاربران باید در اتاق ثبت شوند:

chatroom.register(brad);
chatroom.register(jeff);
chatroom.register(sarah);

ارسال پیام خصوصی

اکنون می‌توانیم بین کاربران پیام خصوصی ارسال کنیم:

brad.send('Hello Jeff', jeff);
sarah.send('Hello Brad, you are the best dev ever', brad);

خروجی این بخش به‌صورت مفهومی چنین خواهد بود:

Brad to Jeff: Hello Jeff
Sarah to Brad: Hello Brad, you are the best dev ever

ارسال پیام عمومی

اگر پارامتر to را ارسال نکنیم، پیام برای همه کاربران اتاق فرستاده می‌شود:

jeff.send('Hello everyone');

خروجی:

Jeff to Brad: Hello everyone
Jeff to Sarah: Hello everyone

توجه کنید که پیام برای خود Jeff ارسال نمی‌شود، چون در منطق برنامه فرستنده از لیست دریافت‌کنندگان حذف شده است.

نسخه کامل مثال

در ادامه، کل کد را یک‌جا می‌بینید:

const User = function (name) {
  this.name = name;
  this.chatroom = null;
};

const Chatroom = function () {
  this.users = {};
};

User.prototype = {
  send: function (message, to) {
    this.chatroom.send(message, this, to);
  },

  receive: function (message, from) {
    console.log(`${from.name} to ${this.name}: ${message}`);
  }
};

Chatroom.prototype = {
  register: function (user) {
    this.users[user.name] = user;
    user.chatroom = this;
  },

  send: function (message, from, to) {
    if (to) {
      to.receive(message, from);
    } else {
      for (let key in this.users) {
        if (this.users[key] !== from) {
          this.users[key].receive(message, from);
        }
      }
    }
  }
};

const brad = new User('Brad');
const jeff = new User('Jeff');
const sarah = new User('Sarah');

const chatroom = new Chatroom();

chatroom.register(brad);
chatroom.register(jeff);
chatroom.register(sarah);

brad.send('Hello Jeff', jeff);
sarah.send('Hello Brad, you are the best dev ever', brad);
jeff.send('Hello everyone');

چرا Mediator Pattern مفید است؟

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

Mediator Pattern این مشکل را حل می‌کند، چون:

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

کاربردهای رایج Mediator Pattern

این الگو در سناریوهای مختلفی کاربرد دارد، از جمله:

  • سیستم‌های گفت‌وگو و پیام‌رسانی
  • ارتباط بین اجزای رابط کاربری
  • هماهنگی بین ماژول‌های مستقل
  • مدیریت eventها در ساختارهای پیچیده
  • سیستم‌هایی که چند شیء باید از طریق یک مرکز مشترک با هم ارتباط داشته باشند

نکته مهم درباره استفاده از Class

در این مثال، پیاده‌سازی با prototype انجام شده است. همین ساختار را می‌توان با ES6 class نیز نوشت. از نظر مفهومی تفاوتی وجود ندارد و فقط syntax تغییر می‌کند.

اگر با class راحت‌تر هستید، می‌توانید همین الگو را به‌صورت class-based هم پیاده‌سازی کنید. با این حال، درک نسخه prototype به فهم بهتر مدل شی‌ءگرایی JavaScript کمک می‌کند.

جمع‌بندی

در this بخش با Mediator Pattern در JavaScript آشنا شدیم. این الگو برای مدیریت ارتباط بین آبجکت‌ها از طریق یک واسطه مرکزی استفاده می‌شود و به کاهش وابستگی مستقیم بین اجزا کمک می‌کند.

در مثال chat room دیدیم که:

  • کاربران مستقیماً با هم ارتباط ندارند
  • همه پیام‌ها از طریق Chatroom مدیریت می‌شوند
  • امکان ارسال پیام خصوصی و عمومی وجود دارد

اگر در پروژه‌ای با چند آبجکت در تعامل روبه‌رو هستید و می‌خواهید ساختار ارتباط آن‌ها منظم‌تر و قابل‌مدیریت‌تر باشد، Mediator Pattern می‌تواند انتخاب بسیار خوبی باشد.

// 0 comments
#JavaScript#الگوهای طراحی#آموزش جاوااسکریپت#prototype#Chat Room#Behavioral Patterns#JavaScript Patterns#Design Patterns#Mediator Pattern

نظرات (0)

نظر خود را بنویسید