Design Patternها راه حل هایی برای مشکلات طراحی نرم افزار است که شما بارها و بارها در توسعه برنامه های کاربردی با آن ها برخورد می کنید. Patternها مربوط به reusable design و تعامل اشیاء هستند.
هدف استفاده از Singleton Pattern
Singleton Pattern یک الگوی طراحی خلاقانه است که به شما امکان می دهد اطمینان حاصل کنید که یک کلاس تنها یک instance دارد، و یک نقطه دسترسی سراسری به این نمونه از کلاس وجود دارد.
Problem
الگوی Singleton دو مشکل را همزمان حل می کند و اصل Single Responsibility Principle را زیر پا می گذارد:
- اطمینان حاصل می دهد که یک کلاس فقط یک instance دارد. اما چرا کسی می خواهد کنترل کند که یک کلاس چه تعداد instance دارد؟ متداول ترین دلیل این امر کنترل دسترسی به منابع مشترک است. برای مثال، یک Database یا یک پرونده.
نحوه عملکرد الگوی Singleton به این صورت است: تصور کنید که شما یک شیء را ایجاد کرده اید، اما بعد از مدتی تصمیم به ایجاد یک نمونه جدید گرفتید. در اینجا به جای ایجاد یک شیء تازه، شما همان شیء را که قبلاً ایجاد کرده اید دریافت خواهید کرد. بنابراین اگر از الگوی طراحی سینگلتون استفاده نکنید به جای استفاده از شی ای که قبلا ساخته اید، شی ای جدید می سازید که این کار از نظر مصرف منابع، هزینه بر و غیر بهینه است.
توجه داشته باشید که اجرای این رفتار با constructor معمولی غیرممکن است زیرا فراخوانی یک سازنده، همیشه با طراحی و بازگشت یک شی جدید همراه است.
Client ها حتی ممکن است متوجه نشوند که تمام مدت با یک شیء مشابه کار می کنند.
- یک نقطه دسترسی سراسری به آن نمونه ارائه می دهد. آن Global Variable هایی که شما برای ذخیره برخی از اشیاء اساسی استفاده می کردید به خاطر دارید؟ در حالی که بسیار مفید هستند، آن ها همچنین بسیار نا امن هستند زیرا هر کدی می تواند محتوای آن متغیرها را بازنویسی کند و برنامه را خراب کند.
دقیقاً مانند یک متغیر Global ، الگوی Singleton به شما امکان می دهد از هر نقطه برنامه به شی Singleton دسترسی داشته باشید. با این حال، آن نمونه را از رونویسی توسط کد دیگر محافظت می کند.
یک طرف دیگر برای این مشکل وجود دارد: شما نمی خواهید کدی که مشکل شماره 1 را حل می کند در سراسر برنامه شما پراکنده شود. خیلی بهتر است که آن را در یک کلاس قرار دهید، به خصوص اگر بقیه کد شما قبلاً به آن وابستگی داشته باشد. امروزه الگوی Singleton به حدی رایج شده است که حتی اگر تنها یکی از مشکلات ذکر شده را برطرف کند، ممکن است افراد آن را Singleton بنامند.
معمولا در در نرمافزارها وظیفه برقراری ارتباط با database را بر عهده یک شی قرار میدهند. بنابراین برای اینکه مطمئن شویم نمونه ها و شی های دیگری برای انجام این کار از کلاس ایجاد نمیشوند، بهترین کار استفاده از الگوی طراحی Singleton است. با این روش برای هر بار برقراری ارتباط با دیتابیس نیاز به ساخت شی جدیدی نخواهیم داشت و تنها با ساخت یک شی از کلاس DBConnection، برای همیشه از آن استفاده خواهیم کرد.
Solution
تمام پیاده سازی های Singleton دارای این دو مرحله مشترک هستند:
در گام اول باید Constructor پیش فرض را private کنید و در گام دوم یک متد استاتیک Creation ایجاد کنید که به عنوان سازنده عمل می کند. این متد از سازنده خصوصی برای ایجاد یک شی استفاده می کند و آن را در یک فیلد static ذخیره می کند. کلیه فراخوانی ها به این متد شی cache شده را برمی گرداند. اگر کد شما به کلاس Singleton دسترسی داشته باشد، می تواند متد استاتیک Singleton را صدا بزند. بنابراین هر وقت آن متد صدا زده می شود، همیشه همان شیء بازگردانده می شود.
به عنوان یک مثال از دنیای واقعی می توان به دولت هر کشور اشاره کرد. دولت نمونه ای عالی از الگوی Singleton است. یک کشور می تواند فقط یک دولت رسمی داشته باشد. صرف نظر از هویت شخصی افراد تشکیل دهنده دولت، عنوان "دولت "X یک نقطه دسترسی جهانی است که گروه افراد مسئول را مشخص می کند.
Structure
کلاس Singleton متد استاتیک getInstance را اعلام می کند که نمونه همان کلاس خود را برمی گرداند. سازنده Singleton باید از کد client مخفی شود. در این صورت فراخوانی متد getInstance تنها راه دریافت شیء Singleton است.
ساختار کد در C#
این کد ساختار الگوی Singleton را نشان می دهد که اطمینان می دهد فقط یک نمونه واحد از کلاس می تواند ایجاد شود.
خروجی کد بالا به صورت زیر می باشد:
مثالی کاربردی از الگوی Singleton
این کد در دنیای واقعی الگوی Singleton را به عنوان یک شی LoadBalancing نشان می دهد. فقط یک نمونه واحد از کلاس LoadBalancer ایجاد می شود زیرا ممکن است سرورها بصورت پویا روشن یا از خط خارج شوند و هر درخواست باید از طریق یک شیء که دارای دانش در مورد وضعیت وب است، برود.
خروجی کد بالا به صورت زیر می باشد:
اما کد بالا را با استفاده از ویژگی ها و قابلیت های جدید NET. می توان به شکل بهینه تری نوشت.
در اینجا یک راه حل زیبا خاص NET. ارائه شده است. الگوی Singleton به سادگی از یک سازنده private و یک متغیر نمونه static که به صورت readonly تعریف شده است استفاده می کند. ایمنی این کار توسط کامپایلر تضمین شده است.