2009-05-27 8 views
5

Ok, la pregunta puede no ser clara. Permítanme dar algunos detalles:¿Cómo puedo hacer que un constructor esté disponible solo para la clase de fábrica?

Digamos que tengo una clase de fábrica de objetos Shoe (CShoe) llamada CFactory. CFactory es una clase singleton que crea y almacena todos los zapatos instanciados utilizando un hashmap simple. A continuación, se accede a través de métodos estáticos para usar los objetos creados.

¿Hay alguna manera de forzar al constructor de CShoe para que solo pueda ser llamado de fábrica? (En otras palabras, asegúrese de que la creación de zapatos solo pueda ser realizada por la clase única de fábrica de zapatos y no por otras clases)

Respuesta

5

Se podría hacer una Shoeinner class de ShoeFactory:

public class ShoeFactory { 

    public static class Shoe { 
     private String name; 

     private Shoe() { 
     } 

     private Shoe(String name) { 
      this.name = name; 
     } 
    } 

    public static Shoe createShoe(String shoeName) { 
     return new Shoe(shoeName); 
    } 
} 

Creo que esta prácticamente cubre todos los casos, excepto .... reflexión:

public class SmellyShoe { 

    public static void main(String[] args) { 
     try { 
      java.lang.reflect.Constructor c = Shoe.class.getDeclaredConstructors()[0]; 
      c.setAccessible(true); 
      Shoe smelly = (Shoe)c.newInstance(null); 
      // grr 
     } catch (InstantiationException e) { 
      e.printStackTrace(); 
     } catch (IllegalAccessException e) { 
      e.printStackTrace(); 
     } catch (IllegalArgumentException e) { 
      e.printStackTrace(); 
     } catch (InvocationTargetException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

¿Desea que el producto sea una clase anidada de la fábrica? –

+0

también puede hacer que CShoe sea una clase interna (no clase estática). Al hacerlo, también evitará que otras personas puedan crear una instancia de CShoe sin tener una instancia de CFactory. – Chii

+0

La reflexión es * siempre * capaz de eludir los modificadores de control de acceso con el método setAccessible(), si su ejemplo puede ejecutarse. Puede detener esto ejecutando un SecurityManager que no permite el permiso "suprimir Access Checks", consulte http://java.sun.com/docs/books/tutorial/essential/environment/security.html –

4

Podría otorgar acceso al paquete de constructor CShoe y poner CShoe y CFactory en el mismo paquete .

1

Dado que desea agregar cada objeto al mapa, también podría mover esta lógica al constructor CShoe: el objeto se agregará a sí mismo.

0

¿Quizás podría pasar el objeto de fábrica al constructor?

public CShoe(CFactory factory) 
{ 
    if (factory == null || 
      !factory.isValid()) // or whatever 
    { 
     throw new IllegalArgumentException(); 
    } 
} 
0

Couldn' t acaba de pasar la instancia de llamada como argumento de un miembro estático de zapato y allí hacer un cheque como "esInst anceOf "que llama al constructor si es verdadero?

1

En primer lugar, si conserva todas las instancias creadas, eso se conoce como una fuga. Seguiré suponiendo que se refiere a una referencia no fuerte, acotada o similar, y que Shoe es inmutable.

Simplemente use el método static para devolver la fábrica.

public final class Shoe implements Footwear { 
    private static final FootwearFactory<Shoe,Something> FACTORY = 
     new FootwearFactory<Shoe,Something>() { 
      ... 
      public Shoe get(Something value) { 
       value = new Something(value); 
       ... 
       return new Show(value); 
      } 
     }; 
    private static FootwearFactory<Shoe,Something> getFactory() { 
     return FACTORY; 
    } 

    private final Something value; 
    private Shoe(Something value) { 
     this.value = value; 
    } 
    ... 
} 
+0

Hummm, así es como funciona una fábrica . Estaba equivocado todo este tiempo ... Entonces, la fábrica debería pertenecer al producto ... ¡¡¡bien !!! –

+0

"Belong" es una palabra muy fuerte. Pero los constructores son parte de su clase, por lo que no es irrazonable que los "constructores virtuales" también deberían existir. –

Cuestiones relacionadas