2009-05-15 13 views
11

Tengo algunas clases que se usan como Singletons. Comparten algunas funcionalidades básicas y extienden el mismo ancestro desde una biblioteca que a su vez no se usa normalmente como Singleton.¿Cómo puedo obtener un Singleton derivado de un tipo base abstracto en Java?

Si pongo la funcionalidad común en una clase base que hereda del ancestro común, obtengo una clase que no tiene sentido crear instancias, por lo que la hice abstracta. Además, dado que todas las clases se usan como Singletons, todas deben tener un método init() y un método getInstance(), que son ambos estáticos. Todos los constructores son, por supuesto, no públicos.

Ahora, ya static es un modificador ilegal que los métodos abstractos, el siguiente no funciona, aunque esto sería exactamente lo que quiero:

class Base extends LibraryClass { 
    protected Base() { 
     // ... constructor 
    } 

    // ... common methods 

    // ILLEGAL! 
    public static abstract void init(); 
    public static abstract <T extends Base>T getInstance(); 
} 

class A extends Base { 
    private static A _INSTANCE; 

    private A() { 
     super(); 
    } 

    public static void init() { 
     _INSTANCE = new A(); 
    } 

    public static A getInstance() { 
     return _INSTANCE; 
    } 
} 

tan sólo pudiera dejar de lado las líneas ilegales en la base clase y listo. Pero ¿cómo puedo expresar que todos los niños de Base deben tener tener estos métodos?

Respuesta

14

Esto no es posible en Java. La existencia de los métodos static no se puede hacer cumplir; ni por abstract ni usando un interface.

Mi solución fue usar IoC de una manera: Creé una clase de fábrica para singletons. Guardaría los singletons en un mapa. La clave sería la clase. De esta manera, podría decir:

A singleton = Factory.create (A.class); 

La principal ventaja de este diseño: puedo crear un método Factory.replace() en casos de prueba pueden anular los embarazos únicos.

+0

¿Por qué necesitamos Singleton aunque ya tengamos Static o Final en Java? la principal renuncia/causa que nos fuerza a adoptar "Singleton" en lugar de "Static, Final"? Aunque para lograr Singleton utilizamos Static.No podría entender este acertijo. Por favor pasa tus comentarios. –

+0

estática final es para constantes que se crean con entusiasmo. Un singleton generalmente se crea perezoso (solo cuando se necesita). Además, la estática final no permite reemplazar la "constante" con una maqueta. Por lo tanto, hacen que las pruebas sean difíciles o incluso imposibles. –

+0

Ver http://stackoverflow.com/questions/11831/singletons-good-design-or-a-crutch –

2

No se puede expresar que las clases secundarias tienen métodos específicos estáticos.

De hecho no debería haber ninguna necesidad de hacer esto ya que los métodos estáticos sólo se llama directamente en las clases hijas (A.init() y A.getInstance() en su ejemplo) y nunca a través de una referencia a la clase base (es decir, métodos estáticos no lo hacen polimorfismo de soporte).

1

¿Por qué no hace todo lo posible y hace que su fábrica (en la clase base) pase un parámetro que indica qué subclase desea que regrese? Hay muchas ventajas para hacerlo de esa manera, y algunas desventajas.

La forma en que intentas hacerlo no tiene mucho sentido ya que los métodos estáticos no tratan la herencia de la misma manera que los métodos normales.

3

Una forma común de tratar de agregar semántica singleton a una clase para la que puede ser inconveniente agregar la semántica correctamente es implementar la funcionalidad singleton en una clase contenedora. Por ejemplo:

public class UsefulThing { 

} 

public final class SingletonOfUsefulThing { 
    private static UsefulThing instance; 

    private SingletonOfUsefulThing() {} 

    public UsefulThing getInstance() { 
     if (instance == null) { 
      instance = new UsefulThing(); 
     } 

     return instance; 
    } 
} 

Esto le permite dar a algunos de los beneficios únicos de primaria a una clase sin algunas de las consecuencias que la aplicación de la semántica únicos en la clase que obliga directamente a tratar y permite cierto margen para cambiar la tipo específico de la clase que está exponiendo como singleton (mediante el uso de una fábrica para crear la instancia, por ejemplo, en lugar de new.

+0

Supongo que su método 'getInstance()' también debería ser 'static '. – Koen

Cuestiones relacionadas