سلام عزیزان کاربران، خوب هستید؟ امیدوارم که شادو سلامت باشید. و روز خوبی را آغاز کرده باشید. ازاینکه همراه ما هستید از شما سپاسگذاریم وامروز در این مقاله قصد داریم مهمترین بخش از Design Pattern به نام Singleton را توضیح دهیم.

قبل از بحث درباره پیاده سازی Singleton، اجازه دهید یکسری سوالات پایه ای را مطرح کنیم و به آنها پاسخ دهیم.
هدف استفاده از Singleton Pattern

همانطور که از نام آن مشخص است، Singleton Pattern فقط اجازه می دهد یک نمونه از class ساخته شود.
چه زمانی نیاز داریم که یک نمونه از کلاس ساخته شود؟

خیلی وقت ها نیاز است که فقط یک نمونه از یک کلاس ساخته شود. مثلاً وقتی که نمی خواهیم وضعیت شی تغییر کند و یا می خواهیم class را به صورت stateless نگه داریم.

به عنوان مثال زمانی که می خواهید یکسری داده های master را یکجا بارگذاری کنید و اجازه دهید مصرف کنندگان داده به جای فراخوانی های متعدد، با ساخت یک نمونه از کلاس، یک فراخوانی به یک کلاس Singleton داشته باشند.

در حالت کلی، در هر برنامه Enterprise پیچیده، می توان به کلاس های Repository و لایه Data Access به صورت Singleton نگاه کرد. درحالیکه معمولاً نمی خواهیم وضعیت در این لایه ها حفظ شود.

از جمله مثال های دیگر می توان به بحث log گیری، تنظیمات (configuration)، Caching و غیره اشاره کرد که می توان آن ها را به صورت Singleton پیاده سازی کرد. چرا که نیاز به یک نقطه مرکزی و سراسری خواهیم داشت تا به این کلاس ها دسترسی داشته باشیم.

گذشته از توضیحات فوق، دیده شده است که برخی از برنامه نویسان بی تجربه یکسری نمونه های اضافی می سازند که نه نتها باعث سربار حافظه می شوند، بلکه کارایی برنامه را تحت تاثیر قرار می دهند.
چرا کلاس های static

به دلایل مختلفی نباید از کلاس های static استفاده کنیم. برخی از این دلایل عبارتند از:

·      موارد مختلفی هست هست که می خواهید Interface ها را در یک کلاس پیاده سازی کنید (برای مثال پیاده سازی IOC- بعداً به توضیح IOC خواهم پرداخت) و به جای پیاده سازی کلاس به صورت static، آن را به صورت Singleton پیاده سازی می کنیم.

·      در صورت نیاز، می توانید از یک کلاس singleton به صورت پارامتر یک متد استفاده کنید درحالیکه نمی توان این کار را با کلاس static انجام داد.
نکته مهم درباره کلاس های Singleton

ایده وضعیت یک کلاس از آنجا نشآت گرفته است که شما نیاز دارید یکسری هماهنگی در محیط های چند نخی (multi-threaded enviroments) ایجاد کنید.

اجازه دهید نگاهی به یک پیاده سازی ساده داشته باشیم.

در اولین مثال، یک Singleton با Lazy loading پیاده سازی شده است و تا زمانیکه فراخواننده، متد GetInstance را برای اولین بار فراخوانی نکند، نمونه ایجاد نمی شود.

public class SingletonClass

{

private static SingletonClass instance = null;

private SingletonClass()

{

}

public static SingletonClass GetInstance

{

get

{

if (instance == null)

{

instance = new SingletonClass();

}

return instance;

}

}

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

private static SingletonClass instance = null;

private static object lockMe = new object();

private SingletonClass()

{

}

public static SingletonClass GetInstance

{

get

{

if (instance == null)

{

lock (lockMe)

{

if (instance==null)

{

instance = new SingletonClass();

}

}

}

return instance;

}

}

و در آخر، Singleton با مقداردهی اولیه static. لطفاً توجه داشته باشید .NET Framework ایمنی thread در زمان مقداردهی اولیه تضمین می کند و دیگر نیازی نیست نگران مسائل هماهنگی باشیم. اگر چه دیگر از مزایای Lazy loading اشیاء برخوردار نخواهیم بود.

private static SingletonClass instance = new SingletonClass();

public SingletonClass()

{

}

private static SingletonClass GetInstance

{

get

{

return instance;

}

}