الگوی Singleton
شناسه پست: 3095
بازدید: 987

Singleton یک الگوی طراحی سازنده است که این امکان را به ما میدهد تا یک نمونه single از یک آبجکت را ایجاد کنیم و آن نمونه single را بین تمام کاربرانی که به آن نیاز دارند به اشتراک بگذاریم. یک نظر رایجی وجود دارد که گفته میشود الگوی Singleton توصیه نمیشود، زیرا باعث به وجود آمدن code smell (چالش هایی که ممکن است برنامه را با خطا مواجه کند) میشود، اما مواردی هم وجود دارد که استفاده از این الگو در آن کاملا مناسب است.

برای مثال، تعدادی از کامپوننتها دلیلی ندارد که بیشتر از یکبار در پروژه نمونه سازی شوند. برای مثال، یک logger را در نظر بگیرید. ثبت کلاس logger به عنوان یک کامپوننت singleton، کاملا مرسوم است، زیرا تمام کاری که ما باید انجام دهیم این است یک رشته را جهت log شدن در نظر بگیریم و logger آن را برای ما در یک فایل بنویسد. سپس چندین کلاس ممکن است نیاز به نوشتن همزمان در یک فایل از thread های مختلف داشته باشند، بنابراین داشتن یک مکان متمرکز برای این منظور همیشه راه حل خوبی به حساب می آید.

این مقاله، بخشی از مجموعه آموزشی زیر است:

اگر میخواهید در عمل، یک logger  را در ASP.NET Core Web API ببینید، میتوانید این مقاله را مطالعه کنید: Log – ASP.NET Core کردن با NLog.

یا شاید گاهی اوقات ما یک task داریم که در آن برخی از داده های یک فایل را میخوانیم و از آنها در پروژه خود استفاده میکنیم. اگر ما از این مسئله اطمینان داشته باشیم که آن فایل در حالیکه داریم آن را میخوانیم، دیگر تغییر نخواهد کرد، میتوانیم یک نمونه single از این آبجکت را ایجاد کنیم که این آبجکت، آن فایل مورد نظر را خوانده و آن را در کل پروژه برای استفاده در کلاسها به اشتراک میگذارد.

در این مقاله، ما قصد داریم به شما نحوه پیاده سازی صحیح الگوی Singleton را در پروژه خود نشان دهیم. منظور ما از پیاده سازی صحیح، این است که کلاس singleton ما، باید thread-safe (یعنی اینکه thread ها، توانایی دسترسی همزمان به یک داده و تغییر آن را نداشته باشند) باشد که در پیاده سازی الگوی Singleton، این یک الزام اساسی میباشد.

سورس را میتوانید از اینجا دانلود کنید: الگوی طراحی Singleton – سورس کد

برای مشاهده لیست کامل مقالات این مجموعه آموزشی، الگوهای طراحی #C را بررسی کنید.

این مقاله، به قسمتهای زیر تقسیم میشود:

آماده سازی پروژه

ما قصد داریم با یک برنامه کنسول ساده، کارمان را شروع کنیم که در آن تمام داده های یک فایل (که شامل شهرها به همراه جمعیت آنها است) را بخوانیم و سپس از آن داده ها استفاده کنیم. بنابراین، برای شروع، یک ایترفیس single ایجاد میکنیم:

بعد از آن، باید یک کلاس برای پیاده سازی اینترفیس ISingletonContainer ایجاد کنیم. نام آن را SingletonDataContainer میگذاریم:

بنابراین، ما اینجا، یک dictionary داریم که در آن نام پایتخت کشورها به همراه جمعیت آنها را از فایل خود گرفته و در آن ذخیره می کنیم. همانطور که میبینیم، ما داده ها را درون سازنده خود، از یک فایل میخوانیم. حالا ما آماده ایم در هر جایی، این کلاس را با نمونه سازی از آن استفاده کنیم. اما آیا این واقعا کاری است که ما باید انجام دهیم؟! نمونه سازی از کلاسی که داده ها را از فایلی میخواند که هرگز تغییر نمیکند (در این پروژه بخصوص، جمعیت شهرها، روزانه تغییر میکند). البته که نه. پس بدیهی است که از یک الگوی Singleton اینجا استفاده کنیم که مینواند خیلی کارساز باشد.

پس بریم تا این الگو را پیاده سای کنیم.

پیاده سازی Singleton

برای پیاده سازی الگوی Singleton، کلاس SingletonDataContainer را تغییر میدهیم:

بنابراین، کاری که ما در اینجا انجام داده ایم این است که با private کردن سازنده خود، آن را از دید کلاس های مصرف کننده پنهان کردیم. سپس، یک single instance از کلاس خود ایجاد کردیم و آن را از طریق ویژگی Instance، افشاسازی کرده ایم.

در حال حاضر، ما میتوانیم ویژگی Instance را هرچند بار که بخواهیم فراخوانی کنیم، اما آبجکت ما، فقط یکبار نمونه سازی میشود و در هر فراخوانی، به اشتراک گذاشته میشود.

اجازه دهید این تئوری را با هم بررسی کنیم:

اگر برنامه را اجرا کنیم، این نتیجه را خواهیم دید:

مثال الگوی singleton

ما اینجا میبینیم که instance خود را چهار بار فراخوانی کردیم، اما آن فقط یکبار initialize شده است که این دقیقا چیزی است که ما میخواهیم. اما پیاده سازی ما ایده آل نیست. اجازه دهید آبجکت خود را به روش lazy بسازیم.

پیاده سازی یک Thread-Safe Singleton

برای پیاده سازی یک thread-safe Singleton با استفاده از نوع Lazy، کلاس خود را تغییر میدهیم:

حالا کلاس ما کاملا thread-safe است. حالا این کلاس به شیوه lazy بارگزاری میشود، به این معنی که instance ما قرار است فقط زمانیکه واقعا مورد نیاز است ایجاد شود. ما حتی اگر بخواهیم میتوانیم با استفاده از ویژگی IsValueCreated، بررسی کنیم که آیا آبجکت ما ایجاد شده است یا خیر.

بسیار عالی. ما پیاده سازی Singleton خود را به اتمام رساندیم.

حالا به طور کامل، میتوانیم آن را در کلاس مصرف کننده خود، استفاده کنیم:

بسیار عالی.

نتیجه گیری

ما مشاهده کرده ایم که اگرچه الگوی Singleton چندان مورد استقبال قرار نمی گیرد، اما در برخی موارد می تواند مفید باشد. بنابراین، همیشه به خود ما بستگی دارد که تصمیم بگیریم از آن استفاده کنیم یا نه. نکته اصلی این است که اگر ما نیاز به استفاده از الگوی Singleton در پروژه خود داشته باشیم، این روش خوبی برای انجام آن است.

نویسنده

امید عباسی
من امید عباسی هستم. سالهاست که در زمینه برنامه نویسی با تکنولوژی دات نت فعالیت میکنم و عاشق این هستم که تجربیات و دانش خودم را در این زمینه با دیگران به اشتراک بزارم. خیلی دوست دارم که نظر و انتقاد خودتون رو در مورد این نوشته برای من بنویسید تا بتونم در آینده، مطالب بهتر و ارزشمندتری را برای شما فراهم کنم. در صورت داشتن هرگونه سوال هم در قسمت دیدگاه ها میتونید با بنده در ارتباط باشید