الگوی یگانه یک الگوی طراحی در مهندسی نرمافزار است. این الگو ایجاد شیء از یک کلاس را محدود میسازد. این الگو زمانی مفید است که در سرتاسر سیستم تنها به یک نمونه از آن کلاس نیاز باشد. این مفهوم عموماً به سیستمهایی که با یک یا تعداد محدودی نمونه بهینهتر کار میکنند، نیز تعمیم داده میشود. واژهٔ آن از مفهوم ریاضی مجموعه تکعضوی (Singleton) برگرفته شده است.
انتقادهایی به استفاده از الگوی یگانه وجود دارد. برخی آن را یک ضدالگو تلقی میکنند، زیرا بیش از حد استفاده میشود، محدودیتهای نابجایی را زمانی که تنها یک نمونه از کلاس لزوماً مورد نیاز نیست، به وجود میآورد و حالت سراسری را به یک برنامه القا میکند. فریمورکها و سیستمعاملهایی مانند اندروید زمانی که نیازمند تخصیص حافظه به برنامهای دیگر باشند، به صورت غیرمنتظره اقدام به زباله روبی اشیاء یگانه میکنند.
طرحهای طراحی Singleton با پیروی از چندین اصل کار میکنند از جمله:
1. تنها یک نمونه از کلاس Singleton باید وجود داشته باشد.
2. کلاس Singleton باید یک نقطه دسترسی global به آن نمونه فراهم کند.
3. نمونه Singleton باید به صورت lazy مقداردهی اولیه شود، به این معنی که تنها زمانی باید ایجاد شود که برای اولین بار درخواست شود.
4. نمونه Singleton باید thread-safe باشد، به این معنی که چندین thread نباید قادر به ایجاد چندین نمونه از کلاس Singleton باشند.
* الگوهای کارخانهٔ انتزاعی، سازنده و نمونهٔ اولیه میتوانند در پیادهسازیهای خود از الگوی یگانه استفاده کنند.
پیادهسازی الگوی یگانه باید قواعد تک شیء بودن و دسترسی سراسری را ارضا کند. این نیازمند یک سازوکار برای دسترسی به عضو یگانهٔ کلاس بدون ایجاد یک شیء از آن کلاس است. نحوه پیادهسازی به این گونه است که کلاس باید یک متد داشته باشد تا یک شیء از همان کلاس را در صورتی که قبلاً ساخته نشده است، برگرداند. برای اطمینان از اینکه نمونهٔ دیگری از این کلاس قابل ایجاد نیست باید دسترسی به constructor کلاس خصوصی باشد. به تفاوت بین یک نمونهٔ ایستا از کلاس و نمونه یگانه توجه کنید: گرچه نمونه یگانه میتواند از طریق ایجاد یک نمونه ایستا پیادهسازی شود ولی میتواند تا زمانی که نیازی به آن پیدا نشده، ساخته نشود و منابع را مصرف نکند. پیادهسازی الگوی یگانه در برنامههایی که قابلیت چند ریسهای دارند نیازمند دقت بیشتری است. اگر دو ریسه همزمان وارد متد مربوط به درخواست شیء یگانه شوند و شیء یگانه هنوز ایجاد نشده باشد، تنها یکی از آن دو ریسه باید شیء را ایجاد کند. راه حل این مسئله استفاده از انحصار متقابل در هنگام ایجاد شیء یگانه است.
مثالهایی که به زبان جاوا در زیر آمدهاند همگی از لحاظ چندریسه بودن مطمئن هستند ولی از لحاظ نسخهٔ جاوا و بارگیری تنبلانه (Lazy Loading) فرق میکنند.
public class SingletonDemo {
private static volatile SingletonDemo instance;
private SingletonDemo() { }
public static SingletonDemo getInstance() {
if (instance == null ) {
synchronized (SingletonDemo.class) {
if (instance == null) {
instance = new SingletonDemo();
}
}
}
return instance;
}
}
در محیط چند ریسهای:
public class SingletonDemo {
private static SingletonDemo instance = null;
private SingletonDemo() { }
public static synchronized SingletonDemo getInstance() {
if (instance == null) {
instance = new SingletonDemo();
}
return instance;
}
}
%7B%7Bالگوهای طراحی}}