الگوی طراحی Singleton که یک الگو از نوع Creational هست تاکید داره که از هر کلاسی فقط و فقط یک نمونه وجود داشته باشه...
خب حالا ببینیم که الگوی Singleton چه مشکلاتی رو حل میکنه؟
این الگو در آن واحد دو مشکل رو حل میکنه که این نقض قانون اول قوانین SOLID هستش:
۱- مطمئن شدن از این که هر کلاس فقط یه نمونه داره. اصلا چرا باید همچین چیزی رو بخوایم؟که ببینیم از هر کلاسی چند نمونه وجود داره؟ یکی از دلایل مهمش کنترل دسترسی به یه سری منابع اشتراکی هستش مثل پایگاه داده یا فایل ها.
حالا چطوری کار میکنه؟ فرض کنید یه نمونه از یه کلاس رو ایجاد کردید اما بعد مدتی می خواید یه نمونه دیگه رو ایجاد کنید به جای این که دیتای تازه ای بگیرید همون نمونه قبلی رو میگیرید.
البته این مورد با Constructor های معمولی غیرممکنه به خاطر این که این نوع سازنده ها همیشه باید یه نمونه جدید رو برگردونن.
۲- فراهم کردن یه نقطه دسترسی Global به اون نمونه. حتما با متغیرهای Global آشنا هستید و از اونا برای ذخیره کردن یه سری Objectها استفاده کردید... این متغیرها با این که خیلی کاربردی هستند اما از سوی دیگه قضیه ممکنه ناامن باشند به این صورت که هر کدی میتونه محتوی اونا رو overwrite کنه و باعث کرش شدن برنامه بشه.
دقیقا مثل متغیرهای Global الگوی Singleton اجازه دسترسی سراسری به اون نمونه رو تو کل برنامه به شما میده با تفاوت این که اجازه نمیده که مقدار اون توسط کدهای دیگه عوض بشه.
خب حالا راه حل چیه؟
تمامی پیاده سازی های الگوی Singleton دو تا مرحله داره:
۱- سازنده پیش فرض کلاس رو به صورت Private در نظر بگیرید برای این که از دسترسی کلاس های دیگه برای ایجاد نمونه جلوگیری کنه.
۲- یه متد استاتیک درست کنید که به عنوان سازنده کلاس عمل کنه، تو لایه پایین تر این متد در واقع سازنده Private کلاس رو صدا میزنه و تو یه فیلد static اونو میریزه و شما هر وقت این کلاس رو صدا بزنید در اصل اون مقدار کش شده برمیگرده.
زنگ تفریح
یه نمونه برای این الگو تو دنیای واقعی هم هست دولت رسمی یه کشور هستش. هر کشوری فقط و فقط میتونه یه دولت رسمی داشته باشه...
خب حالا ساختار این الگو چیه؟
اینجا به دیاگرام UML داریم که به خوبی این الگو رو تشریح میکنه:
خب حالا نحوه پیاده سازیش چطوریه؟
چندین راه برای پیاده سازی این الگو وجود داره حالا ما تو این مقاله ۲ تاش رو بررسی می کنیم، خب بریم سراغ مورد اول:
۱- اول از همه باید یه فیلد static محرمانه به کلاس اضافه کنید.
۲- یه متد پابلیک برای دسترسی به نمونه کلاس درست کنید.
۳-خب حالا باید داخل متد استاتیک lazy initialization رو پیاده سازی کنید این کار باعث میشه که با اولین صدا زدن کلاس یه نمونه از اون کلاس ایجاد بشه و داخل فیلد استاتیک گذاشته بشه و برای بارهای بعدی همون نمونه رو به کلاینت برگردونه.
۴- حالا باید سازنده کلاس رو به صورت محرمانه در نظر بگیرید تو این مورد متد استاتیک به سازنده دسترسی داره اما بقیه کلاس ها دسترسی ندارند.
۵- حالا باید سراغ بقیه کدها برید و هر جا خواستید که یه نمونه از اون کلاس بسازید به جای صدا زدن مستقیم سازنده کلاس از متد استاتیک اون کلاس استفاده کنید.
مورد دوم:
۱- اول از همه باید یه فیلد استاتیک محرمانه به کلاس اضافه کنید و اونو با استفاده از سازنده محرمانه کلاس مقداردهی کنید
۲- با استفاده از کلیدواژه factory یه سازنده برای اون کلاس بسازید که به اون نمونه اشاره میکنه.
خب حالا بریم سراغ مزایا و معایب این الگو:
مزایا:
معایب:
خب بریم سراغ بخش آخر:
ببینیم که رابطه این الگو با الگوهای دیگه چیه؟؟