Design Pattern - Singleton(C#)
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
Definition
Ensure a class has only one instance and provides a global point of access to it.
Participants
The classes and/or objects participating in this pattern are:
- Singleton (LoadBalancer)
- Defines an Instance operation that lets clients access its unique instance. Instance is a class operation.
- Responsible for creating and maintaining its own unique instance.
Sample Code in C#
This structural code demonstrates the Singleton pattern which assures only a single instance (the singleton) of the class can be created.
// --------------------------------------------------------------------------------------------------------------------// <copyright company="Chimomo's Company" file="Program.cs"> // Respect the work.// </copyright>// <summary>// Structural Singleton Design Pattern.// </summary>// --------------------------------------------------------------------------------------------------------------------namespace CSharpLearning{ using System; /// <summary> /// Startup class for Structural Singleton Design Pattern. /// </summary> internal static class MainApp { #region Methods /// <summary> /// Entry point into console application. /// </summary> private 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"); } } #endregion } /// <summary> /// The 'Singleton' class /// </summary> internal class Singleton { #region Static Fields /// <summary> /// The _instance. /// </summary> private static Singleton instance; #endregion // Constructor is 'protected' #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="Singleton"/> class. /// </summary> protected Singleton() { } #endregion #region Public Methods and Operators /// <summary> /// The instance. /// </summary> /// <returns> /// The <see cref="Singleton"/>. /// </returns> public static Singleton Instance() { // Uses lazy initialization. // Note: this is not thread safe. if (instance == null) { instance = new Singleton(); } return instance; } #endregion }}// Output:/*Objects are the same instance*/
This real-world code demonstrates the Singleton pattern as a LoadBalancing object. Only a single instance (the singleton) of the class can be created because servers may dynamically come on-line or off-line and every request must go through the one object that has knowledge about the state of the (web) farm.
// --------------------------------------------------------------------------------------------------------------------// <copyright company="Chimomo's Company" file="Program.cs">// Respect the work.// </copyright>// <summary>// Real-World Singleton Design Pattern.// </summary>// --------------------------------------------------------------------------------------------------------------------namespace CSharpLearning{ using System; using System.Collections.Generic; /// <summary> /// Startup class for Real-World Singleton Design Pattern. /// </summary> internal static class MainApp { #region Methods /// <summary> /// Entry point into console application. /// </summary> private 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); } } #endregion } /// <summary> /// The 'Singleton' class /// </summary> internal class LoadBalancer { #region Static Fields /// <summary> /// The instance. /// </summary> private static LoadBalancer instance; /// <summary> /// The sync lock. /// </summary> private static object syncLock = new object(); #endregion #region Fields /// <summary> /// The random. /// </summary> private Random random = new Random(); /// <summary> /// The servers. /// </summary> private List<string> servers = new List<string>(); #endregion // Constructor (protected) #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="LoadBalancer"/> class. /// </summary> protected LoadBalancer() { // List of available servers this.servers.Add("ServerI"); this.servers.Add("ServerII"); this.servers.Add("ServerIII"); this.servers.Add("ServerIV"); this.servers.Add("ServerV"); } #endregion // Simple, but effective random load balancer #region Public Properties /// <summary> /// Gets the server. /// </summary> public string Server { get { int r = this.random.Next(this.servers.Count); return this.servers[r]; } } #endregion #region Public Methods and Operators /// <summary> /// Get load balancer. /// </summary> /// <returns> /// The <see cref="LoadBalancer"/>. /// </returns> public static LoadBalancer GetLoadBalancer() { // Support multi-threaded applications through 'Double-Check 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; } #endregion }}// Output:/*Same instanceDispatch Request to: ServerIIDispatch Request to: ServerVDispatch Request to: ServerIIDispatch Request to: ServerVDispatch Request to: ServerIIDispatch Request to: ServerIIDispatch Request to: ServerIVDispatch Request to: ServerVDispatch Request to: ServerIIDispatch Request to: ServerVDispatch Request to: ServerIIIDispatch Request to: ServerIIIDispatch Request to: ServerIIDispatch Request to: ServerIIDispatch Request to: ServerIV*/
This .NET optimized code demonstrates the same code as above but uses more modern, built-in .NET features.
Here an elegant .NET specific solution is offered. The Singleton pattern simply uses a private constructor and a static read only instance variable that is eagerly initialized. Thread safety is guaranteed by the compiler.
// --------------------------------------------------------------------------------------------------------------------// <copyright company="Chimomo's Company" file="Program.cs">// Respect the work.// </copyright>// <summary>// .NET optimized Singleton Design Pattern.// </summary>// --------------------------------------------------------------------------------------------------------------------namespace CSharpLearning{ using System; using System.Collections.Generic; /// <summary> /// Startup class for .NET optimized Singleton Design Pattern. /// </summary> internal static class MainApp { #region Methods /// <summary> /// Entry point into console application. /// </summary> private 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); } } #endregion } /// <summary> /// The 'Singleton' class /// </summary> internal 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. #region Static Fields /// <summary> /// The instance. /// </summary> private static readonly LoadBalancer Instance = new LoadBalancer(); #endregion // Type-safe generic list of servers #region Fields /// <summary> /// The random. /// </summary> private Random random = new Random(); /// <summary> /// The servers. /// </summary> private List<Server> servers; #endregion // Note: constructor is 'private' #region Constructors and Destructors /// <summary> /// Prevents a default instance of the <see cref="LoadBalancer"/> class from being created. /// </summary> private LoadBalancer() { // Load list of available servers this.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" }, }; } #endregion // Simple, but effective load balancer #region Public Properties /// <summary> /// Gets the next server. /// </summary> public Server NextServer { get { int r = this.random.Next(this.servers.Count); return this.servers[r]; } } #endregion #region Public Methods and Operators /// <summary> /// Get load balancer. /// </summary> /// <returns> /// The <see cref="LoadBalancer"/>. /// </returns> public static LoadBalancer GetLoadBalancer() { return Instance; } #endregion } /// <summary> /// Represents a server machine /// </summary> internal class Server { #region Public Properties /// <summary> /// Gets or sets the ip. /// </summary> public string IP { get; set; } /// <summary> /// Gets or sets the name. /// </summary> public string Name { get; set; } #endregion }}// Output:/*Same instanceDispatch request to: ServerVDispatch request to: ServerIIDispatch request to: ServerIIDispatch request to: ServerIIIDispatch request to: ServerIDispatch request to: ServerVDispatch request to: ServerVDispatch request to: ServerVDispatch request to: ServerIDispatch request to: ServerVDispatch request to: ServerIVDispatch request to: ServerIDispatch request to: ServerIIIDispatch request to: ServerIVDispatch request to: ServerIV*/