2013-05-13 12 views
5

Użyłem Javy od dłuższego czasu, ale nigdy nie dowiadywałem się, co sprawia, że ​​factories jest tak wyjątkowy. Czy ktoś może mi to wyjaśnić? Czy jest jakikolwiek powód, dla którego powinienem chcieć wdrożyć własną factory (jeśli to nawet możliwe)?Przeznaczenie klas fabrycznych w Javie

+5

Fabryczny wzór umożliwia wybranie implementacji interfejsu w środowisku wykonawczym. Zobacz http://en.wikipedia.org/wiki/Factory_method_pattern –

Odpowiedz

12

fabryczne fantastyczne dla klas oddzielających. Na przykład przyjmijmy wspólny interfejs, Animal i kilka klas, które go implementują. Dog, Cat.

Jeśli nie wiesz, co użytkownik chce wygenerować w czasie wykonywania, nie można utworzyć wskaźnika Dog. To po prostu nie zadziała!

Co można zrobić, to port do oddzielnej klasy, aw czasie wykonywania przekazać do klasy fabrycznej dyskryminatora. Klasa zwróci obiekt. Na przykład:

public Animal getInstance(String discriminator) 
{ 
    if(discriminator.equals("Dog")) { 
     return new Dog(); 
    } 
    // etc. 
} 

i klasy wywołującego po prostu wykorzystuje:

String type = "Dog"; 
Animal value = Factory.getInstance(type); 

To sprawia, że ​​niezwykle czytelny kod, oddziela logikę decyzji z logiki wykonywanej na wartości i oddziela klas poprzez jakiś wspólny interfejs. W sumie całkiem ładny wzór!

+0

Podanie sznurka jako "ciąg polecenia" zawsze wydawało mi się nieco nieprzejrzyste, przechodząc pewnego rodzaju ostateczne pole statyczne jest zawsze ładniej (zazwyczaj typu int, ale tak naprawdę nie ma to znaczenia), więc jeśli chcesz wiedzieć, jakie są opcje, po prostu wejdź do Factory. a następnie autouzupełnienia są opcjami –

+0

Tak, zgadzam się. Jest to podejście, które stosuję, lub używam zewnętrznego "enum". Chciałem tylko złożyć szybki przykład, który nie wymagał żadnych pól. –

0

Używa się ich w połączeniu z prywatnym konstruktorem do tworzenia singletonów. Zapewnia to, że komponent bean (prawdopodobnie usługa) nie może zostać utworzony jako nie-singleton.

Możesz także zabezpieczyć tworzenie klasy za pomocą konstruktora, czyniąc ją prywatną, dzięki czemu możesz dodać trochę logiki w metodzie fabrycznej i nikt nie może jej ominąć.

EDIT: Znam osobę, która miałaby zastąpić konstruktora w każdym fasoli metodą „stworzyć” z parametrami (w celu scentralizowania logikę populacji fasoli), ale nie jestem wielkim fanem tego podejścia.

+0

Nie sądzę, że pytanie dotyczyło statycznej fabryki. – lifus

+0

Z tego pytania nie było jasne, ale masz rację, odpowiedziałem tylko częściowo ... – Igor

4

IMO Największymi zaletami klas Factory są hermetyzacja konfiguracji i danych. Projektowanie interfejsu API jest prawdopodobnie najczęstszym scenariuszem, w którym takie klasy są naprawdę przydatne.

Oferując programistom klasy Factory zamiast bezpośredniego dostępu, mam sposób na łatwe zapobieganie komuś zakłócaniu działania wewnętrznych elementów mojego API. Poprzez klasy Factory kontroluję również, ile wiesz o mojej infrastrukturze. Jeśli nie chcę ci powiedzieć wszystkiego o tym, w jaki sposób zapewniam usługę wewnętrznie, dam ci klasę Factory.

Aby zapewnić niezawodność i jednolite projektowanie, najistotniejsze elementy wewnętrzne należy ująć w klasach Factory.

Oni są sposobem, aby upewnić się, że losowy deweloper, który przychodzi nie będzie:

  • wewnętrzne Przerwa
  • Wzory
  • Zysk niechciane przywileje
  • formaty konfiguracyjne
  • Przerwa
1

Użyj wzorca Factory Method gdy

· klasa nie może przewidzieć klasę obiektów należy go utworzyć.

· klasa chce, aby jej podklasy określały obiekty, które tworzy.

· klasy delegują odpowiedzialność do jednej z kilku podklas pomocników, a chcesz zlokalizować wiedzę o tym, która podklasa pomocnika jest delegatem.

2

Kolejny dobry przykład może być następujący. Wyobraź sobie, że użytkownik chce używać kolekcji somes do wykonywania działań (w tym przypadku wybierz kolekcje, aby utworzyć odwrócony indeks). Możesz utworzyć interfejs taki jak:

interface CollectionsFactory { 
    <E> Set<E> newSet(); 
    <K, V> Map<K, V> newMap(); 
} 

Następnie możesz utworzyć klasę, która jako parametr przyjmuje fabrykę kolekcji.

public class ConcreteInvertedIndex implements InvertedIndex { 
    private final Map<String, Set<Document>> index; 
    private final Set<Document> emptyDocSet;  
    private final CollectionsFactory c; 

    public ConcreteInvertedIndex(CollectionsFactory c){ 
     this.c = c; 
     this.index = c.newMap(); 
     this.emptyDocSet = c.newSet(); 
    } 

//some methods 
} 

I wreszcie to użytkownikowi zdecydować, które zbiory chce używać do wykonywania takich czynności:

CollectionsFactory c = new CollectionsFactory() { 

      @Override 
      public <E> Set<E> newSet() { 
       return new HashSet<E>(); //or you can return a TreeSet per example 
      } 

      @Override 
      public <K, V> Map<K, V> newMap() { 
       return new TreeMap<K, V>();//or you can return an HashMap per example 
      } 
     }; 
     InvertedIndex ii = new ConcreteInvertedIndex(c); 
+0

+1 dla indeksów odwróconych. –

1

Fabryki są szeroko stosowane w JDK wspierać koncepcję SPI (obsługa interfejsu dostawcy) - API przeznaczony do wdrożenia lub rozszerzenia przez stronę trzecią. Na przykład. DocumentBuilderFactory.newInstance() używa skomplikowanego 4-etapowego algorytmu wyszukiwania, aby znaleźć rzeczywistą implementację.

Uważam, że programiści, którzy opracowują biblioteki, a nie aplikacje, powinni preferować podejście "proste jest najlepsze" w projektowaniu oprogramowania.