design pattern Singleton en C #

singleton 

   Singleton (traduit en une seule pièce ou un seul état) mode est le mode de conception relativement simple et le mode commun.

   Parfois , l'ensemble de l' application , il faudra une classe a une et une seule instance, cette fois en utilisant le modèle Singleton peut être conçu. modèle Singleton avec des classes conçues pour assurer non seulement une seule instance dans l'application, mais fournit également une méthode de variable globale accès non globale, appelé point d'accès global, de sorte que pour les langages orientés objet purs ont aucune idée de variables globales est très pratique, comme C #.

   Des exemples d'un compteur utilisé ici pour décrire comment utiliser le modèle Singleton en C #: valeur de comptage variable membre conçu comme un compteur de classe privée, qui est lu et les opérations d'écriture de quatre threads différents, afin d'assurer l'exactitude du comptage, l'ensemble entre le compteur de classe d'application instance exigence inévitable est unique.

la mise en œuvre Singleton 

   deux premières méthodes Singleton Voir les manuels standards de réalisation mis en œuvre, la classe C # suivante en utilisant un pseudo-code:

   Méthode A:

l' utilisation du système;
espace de noms csPattern.Singleton
{
public class Singleton
{
statique Singleton uniSingleton = new Singleton ();
privé Singleton () {}
public static Singleton d'instance ()
{
retour uniSingleton;
}
}
}


   Méthode Deux:

l' utilisation du système;
espace de noms csPattern.Singleton
{
public class Singleton
{
statique Singleton uniSingleton;
privé Singleton () {}
public static instance Singleton ()
{
if (null == uniSingleton)
{
uniSingleton = new Singleton _lazy ();
}
Retour uniSingleton;
}
}
}


   Met en œuvre le motif Singleton de deux techniques: Tout d' abord, utilisez une des variables membres de statique aux instances de magasin « global » pour garantir l' unicité, utilisez une instance de méthode membre statique () au lieu de nouveaux mots - clés pour obtenir l'instance de classe, atteindre globalement visible effet. En second lieu , le constructeur est configuré pour être privé, si vous utilisez les mots - clés pour créer une nouvelle instance de la classe, l'erreur du compilateur, au cas où le temps de programmation d'erreur d' écriture.

   Des exemples des exemples ci - dessus méthode d' initialisation connue sous le nom de deux façon initialisation paresseuse, créez une classe est nécessaire que lorsque la première instance d'une classe et une méthode d'utilisation de peu d' importance ont toujours été comparé à la méthode deux de plus pour économiser les ressources système. Mais la seconde méthode parfois plusieurs instances du phénomène se produit dans les applications multi-thread.
   L'hypothèse ici il y a deux fils: le fil principal et fil 1, lorsque l'instance de la classe est créée peut rencontrer une raison bloquée une période de temps (comme la vitesse du réseau ou la nécessité d'attendre la libération de quelques - unes des ressources utilisées), puis exécutez comme suit:

   le thread principal pour appeler première instance () tente d'obtenir une instance de la méthode de classe, par exemple () pour déterminer les membres de la classe ne créent pas une instance unique, il a commencé à créer une instance. En raison d'un certain nombre de facteurs, le thread principal ne peut pas créer un succès immédiat, mais il faut attendre un certain temps. Discussion 1 est aussi à ce moment pour appeler l'instance () en essayant d'obtenir des instances de la classe, car l'instance n'a pas encore été créé avec succès thread principal, le fil 1 a commencé à créer une nouvelle instance. Le résultat est de créer deux threads sont deux exemples pour compteur de classe, la valeur comptée conduira est remis à zéro, contrairement à l'intention initiale Singleton. La solution à ce problème consiste à synchroniser.

   Voir ici contre obtenir l'exemple suivant: en

   utilisant une méthode:

le système en utilisant l':
l'aide de l'System.Threading,
espace de noms csPattern.Singleton
{
public class Compteur
{
statique uniCounter = new nouveau compteur compteur (); // magasin instance unique.
private int totNum = 0; // valeur de comptage est stockée.
Contre privé ()
{
le Thread.Sleep (100); // suppose ici que le retard en raison de certains facteurs 100 millisecondes.
// Dans le cas d'initialisation non paresseux n'affectera pas le compte. .
}
Instance publique statique contre ()
{
retour uniCounter;
}
public void Inc est un () {totNum ++;} // comptage est incrémentée.
public int GetCounter () {return totNum ;} // obtenir la valeur de comptage actuelle.
}
}


   Ce qui suit est un appel aux clients de classe, où l'on compteur défini quatre threads simultanément en utilisant un compteur pour chaque utilisation de fil 4 fois pour obtenir le résultat correct doit être 16:

using System;
using System.IO;
using System.Threading;
namespace csPattern.Singleton.MutileThread
{
public class MutileClient
{
public MutileClient() {}
public void DoSomeWork()
{
Counter myCounter = Counter.instance(); //方法一
//Counter_lazy myCounter = Counter_lazy.instance(); //方法二
for (int i = 1; i < 5; i++)
{
myCounter.Inc();
Console.WriteLine("线程{0}报告: 当前counter为: {1}", Thread.CurrentThread.Name.ToString(), myCounter.GetCounter().ToString());
}
}
public void ClientMain()
{
Thread thread0 = Thread.CurrentThread;
thread0.Name = "Thread 0";
Thread thread1 =new Thread(new ThreadStart(this.DoSomeWork));
thread1.Name = "Thread 1";
Thread thread2 =new Thread(new ThreadStart(this.DoSomeWork));
thread2.Name = "Thread 2";
Thread thread3 =new Thread(new ThreadStart(this.DoSomeWork));
thread3.Name = "Thread 3";
thread1.Start();
thread2.Start();
thread3.Start();
DoSomeWork(); //线程0也只执行和其他线程相同的工作。
}
}
}


   以下为Main函数,本程序的测试入口:

using System;
namespace csPattern.Singleton
{
public class RunMain
{
public RunMain() {}
static public void Main(string[] args)
{
MutileThread.MutileClient myClient = new MutileThread.MutileClient();
myClient.ClientMain();
System.Console.ReadLine();
}
}
}


   执行结果如下:

   线程Thread 1报告: 当前counter为: 2
   线程Thread 1报告: 当前counter为: 4
   线程Thread 1报告: 当前counter为: 5
   线程Thread 1报告: 当前counter为: 6
   线程Thread 3报告: 当前counter为: 7
   线程Thread 3报告: 当前counter为: 8
   线程Thread 3报告: 当前counter为: 9
   线程Thread 3报告: 当前counter为: 10
   线程Thread 0报告: 当前counter为: 1
   线程Thread 0报告: 当前counter为: 11
   线程Thread 0报告: 当前counter为: 12
   线程Thread 0报告: 当前counter为: 13
   线程Thread 2报告: 当前counter为: 3
   线程Thread 2报告: 当前counter为: 14
   线程Thread 2报告: 当前counter为: 15
   线程Thread 2报告: 当前counter为: 16

   由于系统线程调度的不同,每次的执行结果也不同,但是最终结果一定是16。

   方法一中由于实例一开始就被创建,所以instance()方法无需再去判断是否已经存在唯一的实例,而返回该实例,所以不会出现计数器类多次实例化的问题。
   使用方法二:

using System;
using System.Threading;
using System.Runtime.CompilerServices;
namespace csPattern.Singleton
{
public class Counter_lazy
{
static Counter_lazy uniCounter;
private int totNum = 0;
private Counter_lazy()
{
Thread.Sleep(100); //假设多线程的时候因某种原因阻塞100毫秒
}
[MethodImpl(MethodImplOptions.Synchronized)] //方法的同步属性
static public Counter_lazy instance()
{
if (null == uniCounter)
{
uniCounter = new Counter_lazy();
}
return uniCounter;
}
public void Inc() { totNum ++;}
public int GetCounter() { return totNum;}
}
}


   不知道大家有没有注意到instance()方法上方的[MethodImpl(MethodImplOptions.Synchronized)] 语句,他就是同步的要点,他指定了instance()方法同时只能被一个线程使用,这样就避免了线程0调用instance()创建完成实例前线程1就来调用instance()试图获得该实例。

   根据MSDN的提示,也可以使用lock关键字进行线程的加锁,代码如下:

using System;
using System.Threading;
namespace csPattern.Singleton
{
public class Counter_lazy
{
static Counter_lazy uniCounter;
static object myObject = new object();
private int totNum = 0;
private Counter_lazy()
{
Thread.Sleep(100); //假设多线程的时候因某种原因阻塞100毫秒
}
static public Counter_lazy instance()
{
lock(myObject)
{
if (null == uniCounter)
{
uniCounter = new Counter_lazy();
}
return uniCounter;
}
}
public void Inc() { totNum ++;}
public int GetCounter() { return totNum;}
}
}


   lock()是对一个对象加互斥锁,只允许一个线程访问其后大括号中语句块,直到该语句块的代码执行完才解锁,解锁后才允许其他的线程执行其语句块。

   还可以使用Mutex类进行同步,定义private static Mutex mut = new Mutex();后,修改instance()如下,同样可以得到正确的结果:

static public Counter_lazy instance()
{
mut.WaitOne();
if (null == uniCounter)
{
uniCounter = new Counter_lazy();
}
mut.ReleaseMutex();
return uniCounter;
}


   注意的是,本例中使用方法二要更改方法一的客户程序,去掉Counter_lazy.intance()的注释,并将Counter.intance()注释。

   singleton模式还可以拓展,只要稍加修改,就可以限制在某个应用中只能允许m个实例存在,而且为m个实例提供全局透明的访问方法。

 深圳代孕电13802269370  代孕微13802269370  北京代孕微13802269370

Je suppose que tu aimes

Origine www.cnblogs.com/bbc2020/p/12457297.html
conseillé
Classement