2009-05-27 6 views
5

Ok, la question n'est peut-être pas très claire. Permettez-moi de donner quelques détails:Comment rendre un constructeur disponible uniquement pour la classe d'usine?

Disons que j'ai une classe de fabrique d'objets Shoe (CShoe) appelée CFactory. CFactory est une classe singleton qui crée et stocke toutes les chaussures instanciées à l'aide d'une hashmap simple. Il est ensuite accédé par des méthodes statiques pour utiliser les objets créés.

Existe-t-il un moyen de forcer le constructeur CShoe de sorte qu'il peut seulement appelé par l'usine? (en d'autres termes, assurez-vous que la création de chaussures ne peut être faite que par la classe singleton factory et non par d'autres classes)

Répondre

5

Vous pourriez faire un 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); 
    } 
} 

Je pense que cela couvre à peu près tous les cas, sauf .... réflexion:

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

Vous voulez que le produit soit une classe imbriquée de l'usine? –

+0

vous pouvez également faire de CShoe une classe interne (pas une classe statique). en faisant cela, vous empêcherez également d'autres personnes de créer une instance de CShoe sans avoir une instance de CFactory. – Chii

+0

La réflexion est * toujours * capable de contourner les modificateurs de contrôle d'accès avec la méthode setAccessible(), si votre exemple est capable de s'exécuter. Vous pouvez arrêter ceci en lançant un SecurityManager qui interdit l'autorisation "suppressAccessChecks", voir http://java.sun.com/docs/books/tutorial/essential/environment/security.html –

4

Vous pouvez donner l'accès au package constructeur CShoe et mettre CShoe et CFactory dans le même package .

1

Puisque vous voulez ajouter chaque objet à la carte, vous pouvez aussi déplacer cette logique vers le constructeur CShoe - l'objet va s'ajouter.

0

Vous pourriez peut-être passer l'objet usine dans le constructeur?

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

Couldn » t vous venez de passer l'instance de l'appelant comme argument d'un membre statique de la chaussure et de faire une vérification comme "isInst anceOf "qui appelle le constructeur si vrai?

1

Tout d'abord, si vous conservez toutes les instances créées, cela s'appelle une fuite. Je vais continuer en supposant que vous voulez dire une référence non-forte, limitée ou un tel cache, et aussi que Shoe est immuable. Utilisez simplement une méthode static pour renvoyer l'usine.

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, c'est comme ça que fonctionne une usine . Je me suis trompé tout ce temps ... Alors, l'usine devrait appartenir au produit ... sympa !!! –

+0

"Belong" est un peu un mot fort. Mais les constructeurs font partie de leur classe, il n'est donc pas déraisonnable que les "constructeurs virtuels" soient aussi là pour des cas simples. –

Questions connexes