2009-05-27 7 views
5

OK, pytanie może nie być krystalicznie czyste. Pozwolę sobie podać kilka szczegółów:Jak udostępnić konstruktor tylko klasie fabrycznej?

Załóżmy, że mam klasę fabryczną obiektów Shoe (CShoe) o nazwie CFactory. CFactory to klasa pojedyncza, która tworzy i przechowuje wszystkie zamówione buty za pomocą prostej mapy. Dostęp do tych obiektów odbywa się za pomocą metod statycznych.

Czy istnieje sposób zmuszenia konstruktora CShoe, aby mógł on wywoływać tylko przez fabrykę? (innymi słowy, upewnij się, że tworzenie obuwia może być wykonane tylko przez buty klasy singleton, a nie przez inne klasy)

Odpowiedz

5

Można zrobić Shoeinner class z 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); 
    } 
} 

myślę, że to dość dużo obejmuje wszystkie przypadki, z wyjątkiem .... odbicie:

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

Chcesz, aby produkt był klasą zagnieżdżoną fabryki? –

+0

możesz również uczynić CShoe klasą wewnętrzną (nie statyczną). w ten sposób uniemożliwisz innym osobom stworzenie instancji CShoe bez instancji CFactory. – Chii

+0

Odbicie * zawsze * może odejść od modyfikatorów kontroli dostępu za pomocą metody setAccessible(), jeśli Twój przykład jest w stanie uruchomić. Można to zatrzymać, uruchamiając program za pomocą programu SecurityManager, który uniemożliwia uprawnienie "suppressAccessChecks", zobacz http://java.sun.com/docs/books/tutorial/essential/environment/security.html –

4

Możesz dać dostęp do pakietu konstruktora CShoe i umieścić zarówno CShoe i CFactory w tym samym opakowaniu .

1

Ponieważ chcesz dodać każdy obiekt do mapy, możesz równie dobrze przenieść tę logikę do konstruktora CShoe - obiekt doda się sam.

0

Być może mógłbyś przekazać obiekt fabryczny do konstruktora?

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

mogłem” t po prostu przekazujesz instancję wywołującą jako argument statycznego członka buta, a następnie zaznacz pole "isInst" anceOf ", który wywołuje konstruktor, jeśli jest prawdziwy?

1

Po pierwsze, jeśli zachowujesz wszystkie utworzone wystąpienia, nazywane jest to wyciekiem. Będę kontynuował zakładając, że masz na myśli słabe referencje, ograniczone lub niektóre takie pamięci podręczne, a także, że Shoe jest niezmienny.

Po prostu użyj metody static, aby wrócić do fabryki.

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, więc tak działa fabryka . Myliłem się przez cały ten czas ... Więc fabryka powinna należeć do produktu ... fajnie !!! –

+0

"Belong" to trochę mocne słowo. Ale konstruktorzy są częścią ich klasy, więc nie jest nierozsądne, że "wirtualni konstruktorzy" również powinni istnieć, to proste przypadki. –

Powiązane problemy