83- آموزش جاوااسکریپت | آموزش Singleton Pattern
در این بخش با Singleton Pattern در JavaScript آشنا میشویم؛ الگویی که فقط اجازه میدهد یک نمونه از یک شیء ساخته شود و در تمام بخشهای برنامه همان نمونه مورد استفاده قرار بگیرد.
در این بخش به سراغ Singleton Pattern میرویم؛ الگویی که میتوان آن را یکی از مشتقهای Module Pattern در نظر گرفت.
ایدهی اصلی Singleton بسیار ساده است:
در کل برنامه فقط یک نمونه از یک شیء ساخته میشود و هر بار که آن را فراخوانی کنیم، همان نمونهی قبلی برگردانده میشود.
Singleton Pattern چیست؟
در Singleton Pattern، یک تابع خوداجرا یا IIFE داریم که یک مرجع خصوصی به یک نمونه از شیء نگه میدارد. این مرجع از بیرون قابل دسترسی مستقیم نیست.
هر بار که متد ساخت یا دریافت نمونه فراخوانی شود:
- اگر هنوز نمونهای وجود نداشته باشد، یک شیء جدید ساخته میشود.
- اگر نمونه از قبل ساخته شده باشد، همان نمونهی قبلی برگردانده میشود.
به همین دلیل، در این الگو تکرار فراخوانیها باعث ساخت شیء جدید نمیشود.
چرا از Singleton استفاده میکنیم؟
گاهی در برنامه لازم است فقط یک نمونه از یک موجودیت وجود داشته باشد.
برای مثال:
- اطلاعات کاربر لاگینشده
- تنظیمات سراسری برنامه
- نمونهی اتصال به یک سرویس خاص
- مدیریت state یا configuration مشترک
در این شرایط، Singleton کمک میکند از ایجاد چند نمونهی ناخواسته جلوگیری شود.
نکته مهم درباره Singleton
با وجود کاربردهای مفید، این الگو همیشه محبوب نیست. بسیاری از برنامهنویسان نسبت به Singleton دید انتقادی دارند، چون:
- یک نقطه دسترسی سراسری ایجاد میکند
- ممکن است کپسولهسازی را تضعیف کند
- در بعضی پروژهها اشکالزدایی را سختتر میکند
با این حال، در بعضی سناریوها هنوز میتواند انتخاب مناسبی باشد.
ساختار کلی Singleton Pattern
در این مثال، یک Singleton ساده میسازیم که فقط یک بار شیء مورد نظر را ایجاد میکند:
const Singleton = (function () {
let instance;
function createInstance() {
const object = {
message: 'Object instance'
};
return object;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
بررسی بخشهای مختلف کد
در این ساختار:
1. متغیر instance
این متغیر داخل ماژول تعریف شده و خصوصی است:
let instance;
این متغیر قرار است تنها نمونهی ساختهشده را نگه دارد.
2. تابع createInstance
این تابع مسئول ساخت شیء اولیه است:
function createInstance() {
const object = {
message: 'Object instance'
};
return object;
}
3. متد getInstance
این متد بررسی میکند که آیا نمونهای وجود دارد یا نه:
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
اگر instance خالی باشد، شیء ساخته میشود.
در غیر این صورت، همان نمونهی قبلی برگردانده میشود.
استفاده از Singleton
اکنون میتوانیم یک نمونه دریافت کنیم:
const instanceA = Singleton.getInstance();
console.log(instanceA);
خروجی:
{ message: 'Object instance' }
بررسی اینکه فقط یک نمونه ساخته میشود
اگر دوباره بخواهیم شیء جدیدی از همین Singleton بگیریم:
const instanceA = Singleton.getInstance();
const instanceB = Singleton.getInstance();
console.log(instanceA === instanceB);
خروجی:
true
این نتیجه نشان میدهد که instanceA و instanceB هر دو به یک شیء واحد اشاره میکنند.
چرا نتیجه true است؟
چون در Singleton، بعد از اولین بار ساخت شیء، مقدار آن داخل instance ذخیره میشود و در دفعات بعدی همان مقدار برگردانده میشود.
در نتیجه:
- نمونهی اول ساخته میشود
- نمونهی دوم در واقع ساخته نمیشود
- همان نمونهی اول دوباره بازگردانده میشود
نسخه کامل مثال
در ادامه، کل مثال را یکجا میبینید:
const Singleton = (function () {
let instance;
function createInstance() {
const object = {
message: 'Object instance'
};
return object;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
const instanceA = Singleton.getInstance();
const instanceB = Singleton.getInstance();
console.log(instanceA);
console.log(instanceA === instanceB);
چه زمانی Singleton مناسب است؟
Singleton زمانی مناسب است که واقعاً فقط به یک نمونه مشترک نیاز داشته باشیم.
مثلاً:
- مدیریت session کاربر
- تنظیمات global
- logger مرکزی
- cache مشترک
- service manager
اما اگر برنامه به چند نمونه مستقل نیاز داشته باشد، Singleton انتخاب درستی نیست.
جمعبندی
در این بخش با Singleton Pattern در JavaScript آشنا شدیم.
این الگو تضمین میکند که فقط یک نمونه از یک شیء ساخته شود و تمام فراخوانیهای بعدی همان نمونه را بازگردانند.
نکات اصلی این الگو:
- فقط یک instance ساخته میشود
- نمونه در یک متغیر خصوصی نگهداری میشود
- از بیرون فقط از طریق یک متد عمومی به آن دسترسی داریم
- برای دادهها یا سرویسهای سراسری میتواند مفید باشد
در ادامهی این مبحث، میتوان به سراغ Factory Pattern رفت؛ الگویی که برخلاف Singleton برای ساخت چندین شیء استفاده میشود.