الگوی طراحی Singleton

الگوی طراحی Singleton که یک الگو از نوع Creational هست تاکید داره که از هر کلاسی فقط و فقط یک نمونه وجود داشته باشه...Singletonخب حالا ببینیم که الگوی Singleton چه مشکلاتی رو حل میکنه؟این الگو در آن واحد دو مشکل رو حل میکنه که این نقض قانون اول قوانین SOLID هستش:۱- مطمئن شدن از این که هر کلاس فقط یه نمونه داره. اصلا چرا باید همچین چیزی رو بخوایم؟که ببینیم از هر کلاسی چند نمونه وجود داره؟ یکی از دلایل مهمش کنترل دسترسی به یه سری منابع اشتراکی هستش مثل پایگاه داده یا فایل ها.حالا چطوری کار میکنه؟ فرض کنید یه نمونه از یه کلاس رو ایجاد کردید اما بعد مدتی می خواید یه نمونه دیگه رو ایجاد کنید به جای این که دیتای تازه ای بگیرید همون نمونه قبلی رو میگیرید.البته این مورد با Constructor های معمولی غیرممکنه به خاطر این که این نوع سازنده ها همیشه باید یه نمونه جدید رو برگردونن.Singleton design pattern۲- فراهم کردن یه نقطه دسترسی Global به اون نمونه. حتما با متغیرهای Global آشنا هستید و از اونا برای ذخیره کردن یه سری Objectها استفاده کردید... این متغیرها با این که خیلی کاربردی هستند اما از سوی دیگه قضیه ممکنه ناامن باشند به این صورت که هر کدی میتونه محتوی اونا رو overwrite کنه و باعث کرش شدن برنامه بشه.دقیقا مثل متغیرهای Global الگوی Singleton اجازه دسترسی سراسری به اون نمونه رو تو کل برنامه به شما میده با تفاوت این که اجازه نمیده که مقدار اون توسط کدهای دیگه عوض بشه.خب حالا راه حل چیه؟تمامی پیاده سازی های الگوی Singleton دو تا مرحله داره:۱- سازنده پیش فرض کلاس رو به صورت Private در نظر بگیرید برای این که از دسترسی کلاس های دیگه برای ایجاد نمونه جلوگیری کنه.۲- یه متد استاتیک درست کنید که به عنوان سازنده کلاس عمل کنه، تو لایه پایین تر این متد در واقع سازنده Private کلاس رو صدا میزنه و تو یه فیلد static اونو میریزه و شما هر وقت این کلاس رو صدا بزنید در اصل اون مقدار کش شده برمیگرده.زنگ تفریحیه نمونه برای این الگو تو دنیای واقعی هم هست دولت رسمی یه کشور هستش. هر کشوری فقط و فقط میتونه یه دولت رسمی داشته باشه...خب حالا ساختار این الگو چیه؟اینجا به دیاگرام UML داریم که به خوبی این الگو رو تشریح میکنه:کلاس Singleton یه متد استاتیک به اسم getInstance داره که همون نمونه کلاس خودش رو برمیگردونه. سازنده کلاس هم باید از دید Client مخفی بمونه و تنها راه گرفتن نمونه همون static method باشه.خب حالا نحوه پیاده سازیش چطوریه؟چندین راه برای پیاده سازی این الگو وجود داره حالا ما تو این مقاله ۲ تاش رو بررسی می کنیم، خب بریم سراغ مورد اول:۱- اول از همه باید یه فیلد static محرمانه به کلاس اضافه کنید.۲- یه متد پابلیک برای دسترسی به نمونه کلاس درست کنید.۳-خب حالا باید داخل متد استاتیک lazy initialization رو پیاده سازی کنید این کار باعث میشه که با اولین صدا زدن کلاس یه نمونه از اون کلاس ایجاد بشه و داخل فیلد استاتیک گذاشته بشه و برای بارهای بعدی همون نمونه رو به کلاینت برگردونه.۴- حالا باید سازنده کلاس رو به صورت محرمانه در نظر بگیرید تو این مورد متد استاتیک به سازنده دسترسی داره اما بقیه کلاس ها دسترسی ندارند.۵- حالا باید سراغ بقیه کدها برید و هر جا خواستید که یه نمونه از اون کلاس بسازید به جای صدا زدن مستقیم سازنده کلاس از متد استاتیک اون کلاس استفاده کنید.مورد دوم:۱- اول از همه باید یه فیلد استاتیک محرمانه به کلاس اضافه کنید و اونو با استفاده از سازنده محرمانه کلاس مقداردهی کنید۲- با استفاده از کلیدواژه factory یه سازنده برای اون کلاس بسازید که به اون نمونه اشاره میکنه.خب حالا بریم سراغ مزایا و معایب این الگو:مزایا: از هر کلاسی فقط و فقط یه نمونه وجود داره.برای اون نمونه یه دسترسی سراسری تو کل برنامه دارید. نمونه فقط و فقط یه بار مقداردهی میشه اونم برای بار اولی که صدا زده میشهمعایب:اصل اول SOLID رو نقض میکنه یا همون اصل تک مسئولیتی که این الگو در آن واحد ۲ مشکل رو حل میکنه.تو سیستم های multithreaded ممکنه به مشکل بخورید چون هر thread نمیتونه یه نمونه بسازهبرای تست نویسی احتمالا به مشکل بخوریدخب بریم سراغ بخش آخر:ببینیم که رابطه این الگو با الگوهای دیگه چیه؟؟یه کلاس Facade به یه Singleton تبدیل بشه از اونجا که یه شی از نوعFacade برای اغلب موارد کافیه.الگوهای Abstract Factories, Builders , Prototypes می تونن به عنوان Singleton پیاده سازی بشن.الگوی Flyweight رو یه جورایی میشه شبیه به Singleton دونست البته به شرطی که تمامی state های اشتراکی بین نمونه ها رو تا سر حد یه نمونه کاهش بدید. احتمالا نفهمیدید این قسمت چی شد!! اما نگران نباشید به وقتش سراغ این الگو هم میریم :دی. اما باز با این حال دو تفاوت اساسی بین این دو الگو وجود داره: ۱- از Singleton فقط و فقط یه نمونه وجود داره در صورتی که از Flyweight نمونه های متفاوتی وجود داشته باشه ۲- Singleton objects میتونن mutable باشن در صورتی که Flyweight خلاف این قضیه هستش و immutable هستن.