Design Patterns - explain singleton

I. Introduction

  Singleton pattern should be 23 design patterns in relatively simple, it belongs to create a type of design pattern, to create objects of attention.

Second, the concept

  Singleton is one of the 23 "Gang Of Four" design patterns, it describes how to solve design problems recurring in order to design flexible and reusable object-oriented software, the realization of the object, change, test and reuse more convenient.

Singleton pattern resolves the following issues:

  • How to ensure that only one instance of the class?

  • How easily access the unique instance of the class?
  • How to control class instantiation?

  • How to limit the number of instances of the class?

Singleton is how to solve the above problems?

  • Constructors behind class.
  • Define a unique instance of a class returned public static operation.

The key point of this is to make the design pattern class controls its own instantiation.

Behind class constructor (defined private constructors) to ensure that the class can not be instantiated from the outside.

Use static function easily access the class instance (Singleton.getInstance ()).

Third, to achieve

1, Example lazy single

. 1  the using the System.Threading;
 2  
. 3      public  class SingletonTest
 . 4      {
 . 5          Private  static SingletonTest instance = null ;
 . 6  
. 7          ///  <Summary> 
. 8          /// hidden class constructor (defined private constructors) from the outside to ensure that the class can not be instantiated
 . 9          ///  </ Summary> 
10          Private SingletonTest ()
 . 11          {
 12 is              Console.WriteLine ( " ****** singleton class is instantiated ****** " );
 13          }
 14  
15          // / <Summary> 
16          /// using the static class instance easy access function
 . 17          ///  </ Summary> 
18 is          ///  <Returns> <= Cref See "SingletonTest" /> </ Returns> 
. 19          public  static SingletonTest the GetInstance ()
 20 is          {
 21 is              IF (instance == null )
 22 is              {
 23 is                  instance = new new SingletonTest ();
 24              }
 25  
26 is              return instance;
 27          }
 28  
29          public  void PrintSomething ()
 30         {
31             Console.WriteLine($"当前线程Id为{Thread.CurrentThread.ManagedThreadId}");
32             Console.WriteLine("Singleton Pattern Test");
33         }
34     }

The code in the case of normal single-threaded operation, meets the definition of a single embodiment mode.

However, multi-threaded situation?

We use the following code to test

 1 // 多线程情况
 2             for (int i = 0; i < 10; i++)
 3             {
 4                 Task.Run(
 5                     () =>
 6                         {
 7                             SingletonTest singleton1 = SingletonTest.GetInstance();
 8                             singleton1.PrintSomething();
 9                         });
10             }

The results are as follows

As expected, SingletonTest class is instantiated many times, does not meet the requirements of a singleton, then how to solve this problem?

Since it is a problem caused by multiple threads, it would have to use thread synchronization. We are here to implement the use of locks.

. 1      the using the System;
 2      the using the System.Threading;
 . 3  
. 4      public  class SingletonTest
 . 5      {
 . 6          Private  static SingletonTest instance = null ;
 . 7  
. 8          Private static Object lockObject = new new Object ();
 . 9  
10          ///  <Summary> 
. 11          ///   Hide constructor of the class (defined private constructor) to ensure that the class can not be instantiated from the outside
 12 is          ///  </ Summary> 
13 is          private SingletonTest ()
 14          {
 15              the Thread.Sleep ( 500 );
16              Console.WriteLine ( " ****** singleton class is instantiated ****** " );
 . 17          }
 18 is  
. 19          ///  <Summary> 
20 is          /// using the static class instance easily access functions
 21          / //  </ Summary> 
22 is          ///  <Returns> <= Cref See "SingletonTest" /> </ Returns> 
23 is          public  static SingletonTest the GetInstance ()
 24          {
 25              // double-checked locking means to achieve single-mode embodiment 
26 is             IF ( == null instance)
 27              {
 28                 Lock (lockObject)
 29                  {
 30                     if (instance == null)
31                     {
32                         instance = new SingletonTest();
33                     }
34                 }
35             }
36 
37             return instance;
38         }
39 
40         public void PrintSomething()
41         {
42             Console.WriteLine($"当前线程Id为{Thread.CurrentThread.ManagedThreadId}");
43             Console.WriteLine("Singleton Pattern Test");
44         }
45     }

The code before creating the instance, checking whether the two examples is empty, the first sentence whether it is necessary to empty it (the above code line 26)? why? We imagine such a scenario, in case the class has been initialized instance, do I need to acquire the lock? The answer is not required, so the addition of the first determination condition (the above code, line 26).

Run the test code again, results are as follows:

 From the results, the class is instantiated only once, to solve the multi-threaded lower class is instantiated multiple times problems. But whether this instruction reordering influential? Whether volatile keyword? Welcome chiefs to answer it.

2, starving single Example (recommended)

The first way a bit complicated, you can simply point it? as follows

. 1      the using the System;
 2      the using the System.Threading;
 . 3  
. 4      public  class SingletonTest2
 . 5      {
 . 6          // Static variables are single-mode embodiment 
. 7          Private Instance = new new static Readonly SingletonTest2 SingletonTest2 ();
 . 8  
. 9          Private SingletonTest2 ()
 10          {
 . 11              the Thread .sleep ( 1000 );
 12 is              Console.WriteLine ( "****** singleton class is instantiated ****** " );
 13 is          }
 14  
15         public static SingletonTest2 the GetInstance ()
16         {
17             return Instance;
18         }
19 
20         public void PrintSomething()
21         {
22             Console.WriteLine($"当前线程Id为{Thread.CurrentThread.ManagedThreadId}");
23             Console.WriteLine("Singleton Pattern Test");
24         }
25     }

This implementation utilizes the .NET static keyword static characteristics of the singleton class is instantiated prior to use, and only instantiated once, to ensure that the .NET Framework.

There is a problem in this way, when the members are not using it to create an instance of the class, and can only create an instance of the class members to use the time for it? As shown below

. 1  the using the System;
 2      the using the System.Threading;
 . 3  
. 4      public  class SingletonTest2
 . 5      {
 . 6          // Static variables are single-mode embodiment 
. 7          Private static Readonly Lazy <SingletonTest2> Instance = new new Lazy <SingletonTest2> (() => new new SingletonTest2 ());
 . 8  
. 9          Private SingletonTest2 ()
 10          {
 . 11              the Thread.Sleep ( 1000 );
 12 is              Console.WriteLine ( " ****** ***** initialization singleton instance " );
 13          }
 14  
15         public static SingletonTest2 GetInstance()
16         {
17             return Instance.Value;
18         }
19 
20         public void PrintSomething()
21         {
22             Console.WriteLine($"当前线程Id为{Thread.CurrentThread.ManagedThreadId}");
23             Console.WriteLine("Singleton Pattern Test");
24         }
25     }

We used the Lazy keyword to instantiate the delay.

Fourth, the exception

Notably, the reflection will destroy Singleton , the following code can directly call the private constructor class instantiation again.

1  // damage for single embodiment 
2  var singletonInstance System.Activator.CreateInstance = ( typeof (SingletonTest2), to true );

How to avoid it? Instantiate the class will need to call the constructor, then we can identify the judge added in the constructor. Try to instantiate a second time, it will throw an exception.

. 1          Private static BOOL isInstantiated;
 2  
. 3          Private SingletonTest2 ()
 . 4          {
 . 5              IF (isInstantiated)
 . 6              {
 . 7                  the throw new new Exception ( "has been instantiated, and can not be instantiated again");
 . 8              }
 . 9  
10              isInstantiated = to true;
 . 11              the Thread .sleep ( 1000 );
 12 is              Console.WriteLine ( " ****** singleton class is instantiated ****** " );
 13          }

V. Application

So practical application, which should be used where a single case of model? In the case of the use of this class should exist only one object. Which one use a singleton pattern here?

  • Windows Task Manager
  • HttpContext.Current

VI Summary

As the saying goes, everything has two sides. Singleton pattern ensures that only one instance of the class, also introduces other problems:

  • The only instance variables singleton pattern is the use of static marks, permanent memory will not be recovered GC, long-term occupation of memory
  • In the case of multi-threaded and uses are the same instance, it is necessary to ensure that class members are thread-safe, or may result in data confusion

Download Code: https://github.com/hzhhhbb/SingletonPattern

Seven References

 

Guess you like

Origin www.cnblogs.com/hzhhhbb/p/11373553.html