Aquí está mi ejemplo de resumen de clase singleton:

public abstract class A {
    protected static A instance;
    public static A getInstance() {
        return instance;
    }
    //...rest of my abstract methods...
}

Y aquí es la aplicación concreta:

public class B extends A {
    private B() { }
    static {
        instance = new B();
    }
    //...implementations of my abstract methods...
}

Por desgracia no puedo obtener el código estático en la clase B para ejecutar, por lo que la variable de instancia nunca se pone. He intentado esto:

Class c = B.class;
A.getInstance() - returns null;

y este

ClassLoader.getSystemClassLoader().loadClass("B");
A.getInstance() - return null;

Ejecuta estas en el depurador de eclipse el código estático nunca se ejecuta. La única forma en que podía encontrar para obtener la estática de código que se ejecuta es la de cambiar la accesibilidad en B del constructor público, y llamar a él.

Estoy usando sun-java6-jre en Ubuntu de 32 bits para ejecutar estas pruebas.

InformationsquelleAutor Simon | 2010-03-17

6 Comentarios

  1. 20

    Resumen Singleton? No suena viable para mí. El patrón Singleton requiere un private constructor y de esto ya hace subclases imposible. Usted tendrá que repensar su diseño. El Resumen patrón de Fábrica puede ser más adecuado para el propósito en particular.

    • El propósito del constructor privado en el Singleton es evitar que cualquier persona crear instancias de ella. He conseguido aquí – usted no puede crear una instancia de una clase abstracta, y la subclase tiene un constructor privado.
    • No forzar la subclase abstractos-único y tiene un constructor privado solamente.
    • Singleton no requiere un constructor privado (véase mi respuesta para una solución a esta pregunta con un constructor público).
    • Lo siento, pero su respuesta es inútil, ryvantage. El constructor privado es un requisito clave del patrón singleton. Si usted no tiene uno, entonces usted realmente no tiene un singleton. Alimentos para leer: butunclebob.com/ArticleS.UncleBob.SingletonVsJustCreateOne
  2. 8

    Usted está tratando de conseguir una clase abstracta jugar dos papeles muy diferentes:

    • el resumen de la fábrica de papel de un
      (singleton) servicio que puede tener
      varios sustituibles
      implementaciones de
    • el servicio
      la interfaz de papel,

    y en la parte superior de que usted también desea que el servicio sea de singleton y hacer cumplir ‘singletoness’ en el que toda la familia de clases, por alguna razón usted no está considerando la posibilidad de almacenamiento en caché de las instancias de servicio.

    Alguien (yo lo haría) va a decir que huele muy mal, por múltiples razones
    viola la separación de preocupaciones,
    los únicos hacer pruebas de unidad imposible»,
    etc.

    Alguien más va a decir que está bien-ish, que no necesita un montón de diferentes infraestructuras y tiene una especie de fluido-ish de la interfaz que se ve en algunos muy comunes de terceros (legado) API de Java.

    La parte mala es exigente a los niños a seleccionar qué aplicación debe la fábrica principal método de devolución.
    Esa responsabilidad debe ser empujado hacia arriba y centralizado en el resumen de la superclase. De lo contrario, usted es la mezcla de los patrones que se utilizan en contextos muy diferentes, Resumen de la Fábrica (de los padres a decidir qué familia de clases de clientes van a obtener) y el Método de Fábrica (los niños de las fábricas de seleccionar lo que los clientes obtendrán).

    Fábrica Método también es prácticamente imposible porque no se puede invalidar los métodos estáticos, ni los constructores.

    Hay algunos (feo) de formas de lograr su objetivo, sin embargo:

    public abstract class A{
        public static A getInstance(...){
          if (...)
             return B.getInstance();
          return C.getInstance();
        }
    
        public abstract void doSomething();
    
        public abstract void doSomethingElse();
    
    }
    
    public class B extends A{
        private static B instance=new B();
    
        private B(){
        }
    
        public static B getInstance(){
            return instance;
        }
    
        public void doSomething(){
            ...
        }
        ...
    }
    
    //do similarly for class C

    Los padres también pueden utilizar la reflexión, a instancias de la caché, etc.

    Una prueba más y la extensión de solución amistosa es simplemente estándar de separación de preocupaciones. Los niños no van a ser singleton ya de por sí, pero un paquete de ellos en algunos interna paquete que será el documento como «privado» y un público resumen de los padres en una externa paquete de manejar el almacenamiento en caché o la agrupación de los niños de los casos, hacer cumplir lo que la creación de instancias de la política es necesaria en estas clases.

    • «si (…) volver B. getInstance(); return C. getInstance();» viola «Abrir cerrar principal»
  3. 4

    A.getInstance() nunca llame a un derivado de la instancia, ya que es enlazado estáticamente.

    Yo separaría la creación del objeto del objeto real en sí y crear un adecuado fábrica la devolución de un determinado tipo de clase. No está claro cómo se desea parametrizar que, dado su ejemplo de código es programable a través de un argumento, o es la selección de la clase estática ?

    Usted puede desear reconsiderar el singleton, por cierto. Es común antipattern y hace que la prueba (en particular) un dolor, ya que las clases bajo ensayo deberá proporcionar su propia instancia de la clase singleton. Usted no puede proporcionar una falsa aplicación ni (fácilmente) crear una instancia nueva para cada prueba.

    • A. getInstance() no es necesario llamar a un derivado de la instancia, ya que devuelve la variable de instancia. La derivada de la instancia (clase B), establece la variable de instancia. Salvo que la estática bloque de código no consigue correr. Si no puedo arreglarlo luego de un patrón de Fábrica puede ser mi única opción.
  4. 4

    Singleton son una especie de asqueroso. Resumen insiste en la herencia de la que más a menudo que no quiere evitar si es posible. En general me gustaría repensar si lo que usted está tratando de hacer es la forma más sencilla posible, y si es así, asegúrese de usar una fábrica y no un singleton (singleton son muy difíciles de sustituir en la unidad de pruebas mientras que las fábricas pueden ser invocados para sustituir instancias de prueba fácilmente).

    Una vez que usted comience a buscar en su aplicación como una fábrica de algo abstracto sobrevivirá (bien es evidente que será necesario o puede factor a cabo fácilmente en lugar de una interfaz).

    • +1 por señalar que los únicos son un anti-patrón.
    • Los únicos tienen su lugar, pero por lo general hay un mejor patrón de diseño para lo que usted está haciendo. Un registro es, probablemente, el mejor ejemplo que se me ocurre para un singleton – de esta manera usted no tiene que pasar una variable y se puede acceder a él desde cualquier lugar.
    • Un registro se puede hacer mucho mejor con la Inyección. Un singleton de registro no puede decirle qué clase de vino de mientras que Log l=nuevo Registro(este.getClass()) o alguna variante del mismo puede. Con la inyección es sólo @inject registro o algo similar. Un singleton es también más difícil de la prueba, incluso para el registro. De nuevo un singleton es casi la peor opción (pero ciertamente utilizable)
  5. 3

    Además de los problemas que otros han señalado, teniendo la instance campo en A significa que usted sólo puede tener uno singleton en toda la máquina virtual. Si usted también tiene:

    public class C extends A {
        private C() { }
        static {
            instance = new C();
        }
        //...implementations of my abstract methods...
    }

    … entonces lo de B o C se carga la última voluntad de ganar, y la otra instancia singleton se perderán.

    Esto es sólo una mala manera de hacer las cosas.

    • Gracias – y los otros que dijeron la misma cosa. Esto pone de manifiesto que mi verdadero problema es cómo puedo seleccionar que una de las varias implementaciones de mi interfaz que debo exponer. De la fábrica o de la Fachada parecen buenas maneras de ir.
  6. 1

    He encontrado una mejor manera de utilizar Singleton en la clase abstracta, que el uso de un Mapa estático para mantener la instancia de la subclase.

    public abstract class AbstractSingleton {
    private static Map<String, AbstractSingleton> registryMap = new HashMap<String, AbstractSingleton>();
    AbstractSingleton() throws SingletonException {
    String clazzName = this.getClass().getName();
    if (registryMap.containsKey(clazzName)) {
    throw new SingletonException("Cannot construct instance for class " + clazzName + ", since an instance already exists!");
    } else {
    synchronized (registryMap) {
    if (registryMap.containsKey(clazzName)) {
    throw new SingletonException("Cannot construct instance for class " + clazzName + ", since an instance already exists!");
    } else {
    registryMap.put(clazzName, this);
    }
    }
    }
    }
    @SuppressWarnings("unchecked")
    public static <T extends AbstractSingleton> T getInstance(final Class<T> clazz) throws InstantiationException, IllegalAccessException {
    String clazzName = clazz.getName();
    if (!registryMap.containsKey(clazzName)) {
    synchronized (registryMap) {
    if (!registryMap.containsKey(clazzName)) {
    T instance = clazz.newInstance();
    return instance;
    }
    }
    }
    return (T) registryMap.get(clazzName);
    }
    public static AbstractSingleton getInstance(final String clazzName)
    throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    if (!registryMap.containsKey(clazzName)) {
    Class<? extends AbstractSingleton> clazz = Class.forName(clazzName).asSubclass(AbstractSingleton.class);
    synchronized (registryMap) {
    if (!registryMap.containsKey(clazzName)) {
    AbstractSingleton instance = clazz.newInstance();
    return instance;
    }
    }
    }
    return registryMap.get(clazzName);
    }
    @SuppressWarnings("unchecked")
    public static <T extends AbstractSingleton> T getInstance(final Class<T> clazz, Class<?>[] parameterTypes, Object[] initargs)
    throws SecurityException, NoSuchMethodException, IllegalArgumentException,
    InvocationTargetException, InstantiationException, IllegalAccessException {
    String clazzName = clazz.getName();
    if (!registryMap.containsKey(clazzName)) {
    synchronized (registryMap) {
    if (!registryMap.containsKey(clazzName)) {
    Constructor<T> constructor = clazz.getConstructor(parameterTypes);
    T instance = constructor.newInstance(initargs);
    return instance;
    }
    }
    }
    return (T) registryMap.get(clazzName);
    }
    static class SingletonException extends Exception {
    private static final long serialVersionUID = -8633183690442262445L;
    private SingletonException(String message) {
    super(message);
    }
    }
    }

    De: https://www.cnblogs.com/wang9192/p/3975748.html

Dejar respuesta

Please enter your comment!
Please enter your name here