الگوهای طراحی به منظور حل مشکلات متداول در شیوه برنامه نویسی شی گرا توسط برنامه نویسان باتجربه ایجاد شدند. این نوع مشکلات مستقل از زبانهای برنامه نویسی هستند. یکی از این پرکاربردترین الگوهای طراحی، الگوی طراحی سینگلتون یا Singleton است که در این مطلب با آن آشنا میشویم.
singleton چیست؟
سینگلتون یک الگوی طراحی سازنده (Creational) است که به شما اطمینان میدهد از یک کلاس، تنها یک نمونه یا شی (Object) ساخته شود. بنابراین در هر زمان که استفاده از این کلاس نیاز شود، Singleton یک دسترسی سراسری به تنها شیای که از این کلاس ساخته شده است ایجاد میکند و اجازه ساخت شی جدیدی را از آن کلاس نمیدهد.
الگوی طراحی سینگلتون چه مشکلاتی را برطرف میکند
الگوی Singleton در یک زمان دو مشکل را حل کرده و تنها اصل مسئولیت (Single Responsibility) را نقض میکند:
- این اطمینان را حاصل میکند که از یک کلاس تنها یک شی یا نمونه ساخته شود.
- یک دسترسی سراسری به تنها شی ساخته شده از این کلاس، برقرار میکند.
اما شاید برای شما جای سوال باشد که چرا باید تعداد نمونههای یک کلاس بیشتر از یکی نباشد؟ رایجترین دلیل این امر کنترل دسترسی به برخی از منابع مشترک (Shared Resources) است. زیرا هر یک از این اشیای ساخته شده بخشی از منابع را به خود اختصاص میدهند. تصور کنید که شما یک شی از یک کلاس را ایجاد کردهاید، اما بعد از مدتی تصمیم به ایجاد یک شی دیگر از آن کلاس میگیرید.
بنابراین اگر از الگوی طراحی Singleton استفاده نکنید به جای استفاده از شی ای که قبلا ساخته اید، شی ای جدید میسازید که این کار از نظر مصرف منابع، هزینه بر و غیر بهینه است. جالب است بدانید که ممکن است حتی کلاینتها متوجه نشوند که در تمام مدت در حال استفاده از یک شی بودهاند.
اگر از الگوی طراحی Singleton استفاده نکنیم چه میشود؟
حکایت ضرب المثل معروف «آشپز که دوتا شد، غذا یا شور میشود یا بینمک» مصداق زمانی است که از این الگوی طراحی در موارد لازم استفاده نشود. تصور کنید که ما وظیفه آشپزی یک غذا را با استفاده از برنامه نویسی داریم. بنابراین کلاسی به نام آشپز ایجاد میکنیم تا بتوانیم روشهای پخت و پز (متدهای کلاس) را در آن تعریف کنیم. در نهایت کافی است از کلاس آشپز یک نمونه ایجاد کنیم که نام آن را آشپز اول میگذاریم.
حالا اگر در اینجا از الگوی طراحی سینگلتون استفاده نکنیم، این امکان وجود دارد که دوباره از کلاس آشپز نمونههای جدیدی ایجاد کنیم. در این صورت تعداد آشپزهای ما زیاد میشوند که با این کار علاوه بر اینکه فضا و مواد غذایی بیشتری (منابع سیستم) را مصرف میکنیم، به احتمال زیاد با غذایی بدمزه (نرم افزاری با مشکلاتی زیاد) مواجه خواهیم شد.
الگوی طراحی Singleton در برنامه نویسی
معمولا در در نرمافزارها وظیفه برقراری ارتباط با دیتابیس را بر عهده یک شی قرار میدهند. بنابراین برای اینکه مطمئن شویم نمونهها و شیهای دیگری برای انجام این کار از کلاس ایجاد نمیشوند، بهترین کار استفاده از الگوی طراحی Singleton است. با این روش برای هر بار برقراری ارتباط با دیتابیس نیاز به ساخت شی جدیدی نخواهیم داشت و تنها با ساخت یک شی از کلاس DBConnection، برای همیشه از آن استفاده خواهیم کرد.
بر این اساس تنها یکبار از کلمه کلیدی new در کدهای خود استفاده خواهیم کرد و پس از آن فقط از تابع getInstance الگوی طراحی سینگلتون استفاده میکنیم. این تابع وظیفه دارد که دسترسی به تنها شی ای که از کلاس DBConnection ساخته شده است را برای ما فراهم کند. زیرا امکان وجود ساخت بیش از یک شی از روی این کلاس نه تنها ضرورتی ندارد و علاوه بر اینکه حافظه بیشتری مصرف میکند ممکن است منجر به بروز مشکل در نرم افزار نیز شود.
معایب استفاده از الگوی طراحی singleton
سینگلتون، راهکاری برای تمامی مشکلات نیست و مانند هر ابزار دیگری تنها برای بخش کوچکی از مشکلات میتواند کارآمد باشد.
برنامه نویسان بسیاری به دلایل مختلف با استفاده از سینگلتون موافق نیستند. در ادامه به این مسئله بیشتر میپردازیم.
- Singleton به دلیل این که وابستگیهای پنهانی ایجاد میکند، مانع از انجام تست واحد (unit) میشود. اگر آبجکتها و متدهای مرتبط با Singleton ارتباطی قوی با آن داشته باشند، بدون استفاده از کلاسهای تابعی، نوشتن کدهای قابل تست امکان پذیر نیست.
- Singleton به دلیل اتصالی که در سراسر برنامه ایجاد میکند، اصلاح کد و ردیابی خطاها را دشوار میکند.
- Singleton به شما امکان استفاده از کلاسهای انتزاعی و زیر کلاسها را نمیدهد.
چرا برنامه نویسان توصیه میکنند از singleton استفاده نکنید؟
Singleton به عنوان یک ضد الگو یا Anti Pattern شناخته شده است. یک آنتی پترن، راهکاری با قابلیت استفادهی مجدد میباشد که بر خلاف این که در ابتدا مفید به نظر میرسد، در نهایت مشخص میشود استفاده کردن از آن مضراتی بیشتر از فواید آن دارد. دلایل زیادی میتواند منجر به آنتی پترن بودن یک راهکار شود؛ برای مثال استفاده از یک راهکار در زمان و شرایط خاص گذشته ممکن است مفید بوده باشد اما در شرایط فعلی این گونه نباشد یا این که الگوی مورد نظر از ابتدا راهکاری اشتباه باشد.
جمعبندی:
شما تا اینجا فهمیدید Singleton چیست. با پیاده سازی الگوی طراحی Singleton مشکلات مربوط به ساخت غیر ضروری آبجکتهای مربوط به یک کلاس برطرف میشود. بنابراین اگر بارها و بارها از یک شی بسازیم و به استفاده از آن نیاز داشته باشیم، فقط یک نسخه از آن شی وجود دارد که در نرم افزار فراخوانی خواهد شد. با این کار تنها همان شی در حافظه ذخیره میشود و این امر باعث بهینهسازی در مصرف منابع خواهد شد. اما امروزه، Singleton رسما به عنوان یک آنتی پترن شناخته شده و استفاده از آن توصیه نمیشود.