2010-06-26 18 views
6

Esto puede sonar como una idea extraña y todavía no lo he pensado bien.Generando singletons

Digamos que tiene una aplicación que termina requiriendo un cierto número de singleton para hacer algunas E/S, por ejemplo. Podrías escribir un singleton y básicamente reproducir el código tantas veces como sea necesario.

Sin embargo, como programadores se supone que tenemos que inventar soluciones que eviten la redundancia o la repetición de cualquier tipo. ¿Cuál sería la solución para hacer varias cosas que podrían actuar como singleton?

P.S: Esto es para un proyecto en el que no se puede usar un marco como Spring.

+4

Múltiples cosas es de alguna manera contradictorio con el término de un singleton. Considere usar el patrón de fábrica. – Andreas

+0

Singletons por definición tienen una sola instancia en el proceso. Entonces, cuando dice múltiples singletons, ¿quiere decir A. Múltiples instancias del mismo objeto? B. Un código genérico para diferentes clases singleton para usar para restringir cada una de ellas a una única instancia –

+1

Como estás hablando de Spring, ¿estás usando una aplicación web JSP/Servlet? ¿Has considerado 'ServletContextListener'? Singletons en una webapp huele. – BalusC

Respuesta

3

Usted podría introducir una abstracción de esta manera:

public abstract class Singleton<T> { 
    private T object; 

    public synchronized T get() { 
    if (object == null) { 
     object = create(); 
    } 
    return object; 
    } 

    protected abstract T create(); 
} 

Luego, para cada producto único, sólo tiene que escribir esto:

public final Singleton<Database> database = new Singleton<Database>() { 
    @Override 
    protected Database create() { 
    // connect to the database, return the Database instance 
    } 
}; 

public final Singleton<LogCluster> logs = new Singleton<LogCluster>() { 
    ... 

continuación, puede utilizar los únicos escribiendo database.get(). Si el singleton no se ha creado, se crea y se inicializa.

La razón la gente probablemente no hacen esto, y prefieren simplemente repetidamente escribir algo como esto:

private Database database; 

public synchronized Database getDatabase() { 
    if (database == null) { 
    // connect to the database, assign the database field 
    } 
    return database; 
} 

private LogCluster logs; 

public synchronized LogCluster getLogs() { 
    ... 

se debe a que, al final, es sólo una más línea de código para cada producto único, y la probabilidad de que el patrón de inicialización de singleton sea incorrecto es bastante baja.

+3

Esto es ... aterrador. ¿Conectar el DB durante la construcción de un Singleton? – BalusC

+3

Eso es una complicación excesiva al máximo allí mismo. –

+1

@Gnarly Básicamente estoy argumentando que es por eso que * no * haces esto. Personalmente prefiero Guice (aunque eso puede ser complicado a su manera.) –

1

¿Qué tal pasar un parámetro a la función que crea el singleton (por ejemplo, su nombre o especialización), que sepa crear un singleton para cada parámetro único?

+0

Eso sería ideal. Esto va junto con la sugerencia de usar un patrón de fábrica. –

2

Existe un patrón multiton. De todos modos, estoy 60% seguro de que la solución real al problema original es un RDBMS.

+0

+1 para Multiton Pattern –

+0

No había oído hablar de este patrón antes y suena similar a lo que Spring debe hacer internamente. Aquí hay un enlace para referencia futura: http://j2eeblogger.blogspot.com/2007/10/singleton-vs-multiton-synchronization.html –

-1

Sé que preguntó acerca de Java, pero aquí es una solución en PHP como un ejemplo:

abstract class Singleton 
{ 
    protected function __construct() 
    { 
    } 

    final public static function getInstance() 
    { 
     static $instances = array(); 

     $calledClass = get_called_class(); 

     if (!isset($instances[$calledClass])) 
     { 
      $instances[$calledClass] = new $calledClass(); 
     } 

     return $instances[$calledClass]; 
    } 

    final private function __clone() 
    { 
    } 
} 

A continuación, que acaba de escribir:

class Database extends Singleton {} 
+0

-1 - Este enfoque no funciona para Java. Los métodos estáticos no se heredan, por lo que no hay equivalente a 'get_called_class'. –

+0

Esto es correcto, pero como también estoy interesado en PHP, te votaré como máximo ya que te tomaste la molestia de publicar una muestra de código. –

3

Sin embargo, como programadores estamos se supone que debe aportar soluciones ingeniosas que eviten la redundancia o la repetición de cualquier tipo.

Eso no es correcto. Como programadores, se supone que debemos encontrar soluciones que cumplan con los siguientes criterios:

  • cumplen con los requisitos funcionales; p.ej. realizar según lo requerido sin errores,
  • se entregan dentro del plazo obligatorio,
  • son mantenibles; p.ej. el siguiente desarrollador puede leer y modificar el código,
  • funciona lo suficientemente rápido para la tarea en cuestión, y
  • pueden reutilizarse en tareas futuras.

(Estos criterios son más o menos clasificadas por prioridad decreciente, aunque diferentes contextos pueden dictar un orden diferente.)

inventiva no es un requisito, y "evitar [ing] redundancia o repetición de ningún tipo" tampoco lo es. De hecho, ambos pueden ser claramente dañinos ... si el programador ignora los criterios reales.

Llevando esto a su pregunta. Solo debe buscar formas alternativas de hacer singletons si realmente va a hacer que el código sea más fácil de mantener. Las soluciones "inventivas" complicadas bien pueden regresar a mordida usted (o las personas que tienen que mantener su código en el futuro), incluso si logran reducir el número de líneas de código repetido.

Y como otros han señalado (por ejemplo, @BalusC), el pensamiento actual es que el patrón singleton debería ser evitado en muchas clases de aplicación.

+0

He visto una gran cantidad de errores tipográficos de mi nombre antes, pero aún no :) :) – BalusC

+0

@BalusC - Solucionado. Lo siento. –

+0

Por un lado, si esto respondía la pregunta, lo votaría.Por otro lado, parece una respuesta argumentativa a un comentario innecesario en la publicación original (aunque los PO defectuosos pueden ser la causa de esta pregunta). –

2

@BalusC tiene razón, pero lo diré con más fuerza, los Singleton son malvados en todos los contextos. Webapps, aplicaciones de escritorio, etc. Simplemente no lo hagas.

Todo un singleton es en realidad un fajo de datos global. La información global es mala. Hace las pruebas unitarias apropiadas imposibles. Hace que rastrear bichos raros sea mucho, mucho más difícil.

El libro de la Banda de los Cuatro es totalmente erróneo aquí. O al menos obsoleto por una década y media.

Si solo desea una instancia, tenga una fábrica que solo fabrique una. Es fácil.