2009-06-17 10 views
6

Tuve otra pregunta de la entrevista. Pensé que esto era una tontería, pero tal vez hay algo que me falta. La pregunta preguntó qué patrón de GoF es esto (respuesta: singleton) y, si hay algún problema, cómo los resuelvo.Extracto del código de Singleton, una pregunta de la entrevista

No veo ningún problema. Mencioné que esto nunca se libera y espero que de este patrón. Eso es todo lo que dije. ¿Me estoy perdiendo de algo?

public class Class1 
{ 
    private static Class1 oInstance = null; 
    private Class1() { } 
    public static Class1 GetInstance() 
    { 
     if (oInstance == null) 
     { 
      oInstance = new Class1(); 
     } 
     return oInstance ; 
    } 
} 

Respuesta

16

Seguridad de subprocesos: pueden crearse múltiples instancias si se llama a GetInstance() desde hilos de la competencia.

3

Tiene una condición de carrera potencial en código multiproceso. Dos subprocesos podrían superar la comprobación nula antes de que el constructor del otro subproceso se complete, de modo que ambos puedan terminar construyendo la clase.

1

Existe un problema potencial con esto si tiene una aplicación multiproceso. Esto puede hacer que se construya más de una instancia si se solicitan dos hilos al mismo tiempo.

Echaré un vistazo a esta página en Singletons in C#. Muestra el problema en detalle, así como mejores opciones.

13

Ver: An obvious singleton implementation for .NET?

hay múltiples preocupaciones que desee considerar cuando se implementa un patrón Singleton.

  • ¿Qué pasa cuando múltiples llamadas de solicitud de el singleton de múltiples hilos. Simplemente debería funcionar.
  • Cuando se llama al ejemplo de Singleton . Es posible que desee diferirlo para que ocurra en la primera llamada que solicite el singleton, es posible que desee primero crear una instancia en otro momento.
  • ¿Debería la gente poder heredar de su clase singleton? ¿Cuál debería ser el comportamiento?
  • Debería ser posible cambiar su instancia singleton a una instancia diferente después de que se haya instanciado el singleton. Responder afirmativamente a esto viola el patrón de singleton, por lo que, en general, el campo que contiene los singletons debe ser , solo.
  • Diseño de API, si utiliza una propiedad o método para devolver la instancia de Singleton.
  • Algunos personas dicen singletons evil. Deberías incluso estar considerándolo en primer lugar. Esto ha sido discutido muy a menudo un buen punto de partida es http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx

El siguiente es un buen patrón de propósito general que podría seguir. Su hilo seguro, sellado, usa propiedades y difiere instansiates el singleton.

public sealed class Singleton 
{ 
    static class SingletonCreator 
    { 
     // This may seem odd: read about this at: http://www.yoda.arachsys.com/csharp/beforefieldinit.html 
     static SingletonCreator() {} 
     internal static readonly Singleton Instance = new Singleton(); 
    } 

    public static Singleton Instance 
    { 
     get { return SingletonCreator.Instance; } 
    } 
} 
3

El código no es seguro para subprocesos.Para que sea lo que necesita para hacer esto:

public class Class1 
{ 
    private static Class1 oInstance = null; 
    private Class1() { } 
    public static Class1 GetInstance() 
    { 
     if (oInstance == null) 
     { 
      lock(typeof(Class1)) 
      { 
       if (oInstance == null) 
       { 
        oInstance = new Class1(); 
       } 
      } 
     } 
     return oInstance ; 
    } 
} 

Ésta es la forma más eficiente de la carga de la instancia con pereza, ya que sólo molesta para bloquear (puede ser caro) cuando se sospecha la instancia no se creará una instancia para la próxima llamada. Revisar nuevamente una vez en la cerradura asegura que solo se creará una instancia una vez.

+0

+1 ... aunque personalmente no usaría typeof (Class1) para el bloqueo, sino simplemente una instancia de objeto que no se usa para nada más. –

+3

Estoy absolutamente con Fredrik Mörk: bloquear un objeto tipo es una mala práctica (como bloquear esto). Cada código puede inmovilizarlo (incluso en aplicaciones) si bloquea objetos tipo (y cada código que tenga acceso a una instancia puede bloquearlo si lo bloquea). lock (typeof (Class1)) {Class1.GetInstance(); } y estás en serios problemas ... –

+0

Garry, mira el patrón en mi respuesta, limpiador de camino IMHO –

0

¿Cuál es la solución?

public class Class1 
{ 
    private static Class1 oInstance = new Class1(); 
    private Class1() { } 
    public static Class1 GetInstance() 
    { 
     return oInstance ; 
    } 
} 
+0

Esto es bueno, pero al mínimo básico oLa presencia debe ser de solo lectura y no difiere cargar el singleton ... –

6

Otros mencionaron la seguridad de la rosca. También está el hecho de que olvidaron marcarlo como sealed, por lo que podría heredarlo y crear varias instancias de esa manera.

+0

+1 Recopilé esta preocupación en mi respuesta –

+0

¿El constructor predeterminado privado no previene la creación de subclases? – Andrew

+0

@Andrew ... no, no, pruébalo tú mismo ... –

0

No trabaje en esa empresa. El patrón singleton no es un patrón frecuentemente utilizado y su aplicabilidad en un sistema OO puro es cuestionable. Deshacer un patrón singleton es un gran problema si alguna vez tiene que volver a convertirlo en un objeto normalmente construido.

+0

Esa es una afirmación muy amplia. Creo que depende del tipo de desarrollo que hagas. Mi equipo escribe software de sistema en C++ y Java y Singletons se usan PESADAMENTE en ambos. – xeon

+0

Es una afirmación general, sin embargo, en general, estos días me gusta guardar todas mis dependencias en un kernel que maneja todas estas dependencias en lugar de tener todas mis dependencias extendidas en mi aplicación. Tener singleton hace las pruebas mucho más difíciles. –

+0

Pensé que esto también podría ser cierto, hasta que me di cuenta de que eran súper útiles en mi proyecto actual ... básicamente es una cuestión de instancias, a veces solo quieres una instancia de tu objeto y nada más. – alchemical

Cuestiones relacionadas