الگوی Singleton

الگوی Singleton(یگانه) در دسته الگوهای ایجادی قرار دارد. اطمینان از اینکه که یک کلاس تنها یک نمونه دارد و یک نقطه کلی دسترسی به آن را فراهم می کند. به عبارت دیگر تعریف کلاسی که در سرتاسر برنامه تنها یک نمونه از آن بتوان ایجاد کرد. UML class diagram شركت كنندگان کلاس ها و اشیاء شرکت کننده در این الگو عبارتند از:یگانه Singleton ( در مثال دنیای واقعی LoadBalancer)یک عملیات نمونه سازی (Instance operation) را تعریف می کند که به کلاینت اجازه می دهد به نمونه منحصر به فرد خود دسترسی پیدا کند. نمونه (Instance) یک عملیات کلاس است.مسئول ایجاد و حفظ یک نمونه منحصر به فرد خود است.به عبارت دیگر Singleton کلاسی که قرار است الگوی Singleton در آن پیاده سازی شود. Singleton() سازنده خصوصی (private) کلاس برای جلوگیری از نمونه سازی از آن از بیرون کلاس.ساختار کلی کدالگوی Singleton را نشان می دهد که تنها یک نمونه (singleton) از کلاس را ایجاد می کند. using System; namespace DoFactory.GangOfFour.Singleton.Structural { /// <summary> /// MainApp startup class for Structural /// Singleton Design Pattern. /// </summary> class MainApp { /// <summary> /// Entry point into console application. /// </summary> static void Main () { // Constructor is protected -- cannot use new Singleton s1 = Singleton.Instance (); Singleton s2 = Singleton.Instance (); // Test for same instance if (s1 == s2) { Console.WriteLine ("Objects are the same instance"); } // Wait for user Console.ReadKey (); } } /// <summary> /// The 'Singleton' class /// </summary> class Singleton { private static Singleton _instance; // Constructor is 'protected' protected Singleton () { } public static Singleton Instance () { // Uses lazy initialization. // Note: this is not thread safe. if (_instance == null) { _instance = new Singleton (); } return _instance; } } } OutputObjects are the same instanceیاpublic sealed class Singleton { private static readonly Singleton uniqueInstance = new Singleton( ); Singleton( ){ } public static Singleton Instance() { return uniqueInstance; } } class Test { static void Main() { var s1 = Singleton.Instance(); var s2 = Singleton.Instance(); var s3 = Singleton.Instance(); Console.WriteLine("s1 == s2 ? {0}", (s1 == s2)); Console.WriteLine("s2 == s3 ? {0}", (s2 == s3)); Console.ReadKey(); } } /* OUTPUT:s1 == s2 ? Trues2 == s3 ? True*/کد در دنیای واقعیالگوی Singleton را به عنوان یک شی LoadBalancing نشان می دهد.فقط یک instance (singleton) از کلاس می تواند ایجاد شود زیرا سرورها ممکن است به طور پویا به صورت آفلاین و یا آنلاین وارد شوند و هر درخواست باید یک شی که دارای اطلاعات در مورد وضعیت مزرعه (وب) می باشد. using System; using System.Collections.Generic; using System.Threading; namespace DoFactory.GangOfFour.Singleton.RealWorld { /// <summary> /// MainApp startup class for Real-World /// Singleton Design Pattern. /// </summary> class MainApp { /// <summary> /// Entry point into console application. /// </summary> static void Main () { LoadBalancer b1 = LoadBalancer.GetLoadBalancer (); LoadBalancer b2 = LoadBalancer.GetLoadBalancer (); LoadBalancer b3 = LoadBalancer.GetLoadBalancer (); LoadBalancer b4 = LoadBalancer.GetLoadBalancer (); // Same instance? if (b1 == b2 && b2 == b3 && b3 == b4) { Console.WriteLine ("Same instance\n"); } // Load balance 15 server requests LoadBalancer balancer = LoadBalancer.GetLoadBalancer (); for (int i = 0; i < 15; i++) { string server = balancer.Server; Console.WriteLine ("Dispatch Request to: " + server); } // Wait for user Console.ReadKey (); } } /// <summary> /// The 'Singleton' class /// </summary> class LoadBalancer { private static LoadBalancer _instance; private List<string> _servers = new List<string> (); private Random _random = new Random (); // Lock synchronization object private static object syncLock = new object (); // Constructor (protected) protected LoadBalancer () { // List of available servers _servers.Add ("ServerI"); _servers.Add ("ServerII"); _servers.Add ("ServerIII"); _servers.Add ("ServerIV"); _servers.Add ("ServerV"); } public static LoadBalancer GetLoadBalancer () { // Support multithreaded applications through // 'Double checked locking' pattern which (once // the instance exists) avoids locking each // time the method is invoked if (_instance == null) { lock (syncLock) { if (_instance == null) { _instance = new LoadBalancer (); } } } return _instance; } // Simple, but effective random load balancer public string Server { get { int r = _random.Next (_servers.Count); return _servers[r].ToString (); } } } } OutputSame instanceServerIIIServerIIServerIServerIIServerIServerIIIServerIServerIIIServerIVServerIIServerIIServerIIIServerIVServerIIServerIV کد بهینه شده در.NET کد بهینه شده .NET کد مشابه را نشان می دهد همانطور که در بالا ذکر شد، اما از ویژگی های مدرن، ساخته شده در .NET استفاده می کند.در اینجا یک راه حل ویژه برای دات نت ارائه شده است. الگوی Singleton به سادگی با استفاده از یک سازنده خصوصی ( private constructor ) و یک متغیر مستقل به عنوان فقط خوانی ( static readonly ) است که تنبل مقداردهی اولیه ( lazily initialized ) شده است. ایمنی نخ ( Thread safety ) توسط کامپایلر تضمین شده است. using System; using System.Collections.Generic; namespace DoFactory.GangOfFour.Singleton.NETOptimized { /// <summary> /// MainApp startup class for .NET optimized /// Singleton Design Pattern. /// </summary> class MainApp { /// <summary> /// Entry point into console application. /// </summary> static void Main () { LoadBalancer b1 = LoadBalancer.GetLoadBalancer (); LoadBalancer b2 = LoadBalancer.GetLoadBalancer (); LoadBalancer b3 = LoadBalancer.GetLoadBalancer (); LoadBalancer b4 = LoadBalancer.GetLoadBalancer (); // Confirm these are the same instance if (b1 == b2 && b2 == b3 && b3 == b4) { Console.WriteLine ("Same instance\n"); } // Next, load balance 15 requests for a server LoadBalancer balancer = LoadBalancer.GetLoadBalancer (); for (int i = 0; i < 15; i++) { string serverName = balancer.NextServer.Name; Console.WriteLine ("Dispatch request to: " + serverName); } // Wait for use Console.ReadKey (); } } /// <summary> /// The 'Singleton' class /// </summary> sealed class LoadBalancer { // Static members are 'eagerly initialized', that is, // immediately when class is loaded for the first time. // .NET guarantees thread safety for static initialization private static readonly LoadBalancer _instance = new LoadBalancer (); // Type-safe generic list of servers private List<Server> _servers; private Random _random = new Random (); // Note: constructor is 'private' private LoadBalancer () { // Load list of available servers _servers = new List<Server> { new Server { Name = "ServerI", IP = "120.14.220.18" }, new Server { Name = "ServerII", IP = "120.14.220.19" }, new Server { Name = "ServerIII", IP = "120.14.220.20" }, new Server { Name = "ServerIV", IP = "120.14.220.21" }, new Server { Name = "ServerV", IP = "120.14.220.22" }, }; } public static LoadBalancer GetLoadBalancer () { return _instance; } // Simple, but effective load balancer public Server NextServer { get { int r = _random.Next (_servers.Count); return _servers[r]; } } } /// <summary> /// Represents a server machine /// </summary> class Server { // Gets or sets server name public string Name { get; set; } // Gets or sets server IP address public string IP { get; set; } } } OutputSame instanceServerIVServerIVServerIIIServerVServerIIServerVServerIIServerIIServerIServerIVServerIVServerIIServerIServerVServerIVنکته اول: پیاده سازی الگوی singleton برای وب، با پیاده سازی این الگو در سایر کد ها فرق داردنکته دوم: در aspnetcore گفته شده الگوی singleton درون کلاس پیاده سازی نکنید. بجای آن ، هنگام تزریق وابسطی نوع آن (نوع تزریق) را singleton قرار دهید.منبع