Rodzina factory pattern kilka pytań

0

Otrzymałem już odpowiedź na 1 i 3 pytanie.

  1. Widziałem, że czasami jest tworzona abstrakcyjna klasa/interfejs dla głównej fabryki natomiast korzysta się z konkretnych fabryk rozszerzających/implementujących rzeczoną klasę/interfejs na zasadzie:
AbstractFactory factory1 = new ConcreteFactoryOne();
AbstractFactory factory2 = new ConcreteFactoryTwo();

Widziałem też inną implementację polegającą na utworzeniu czegoś w rodzaju FactoryProducer i metodzie statycznej która zwracała daną fabrykę:

AbstractFactory factory1 = FactoryProducer.getFactory("ConcreteFactoryOne");
AbstractFactory factory2 = FactoryProducer.getFactory("ConcreteFactoryTwo");

Czyli to co wyżej (? tak mi sie wydaje) tylko z dodatkową klasą owijającą całość metodą statyczną. Czy któraś z tych implementacji jest lepsza/gorsza, czy można ten pattern tak samo jak factory method zaimplementować w dwojaki sposób?

2. Wiem, że można zaimplementować factory method z pomocą enuma, nie wiem czy jest to poprawne, czy nie jak myślicie?

  1. Wszędzie przekazujemy Stringa i trochę mnie to dziwi. Czy w jakiś sposób można wykorzystać enum? Jeżeli tak to jak? Bo zastanawia mnie jak to wygląda w praktycznej sytuacji. Mamy np. dwie postacie Rogue i Paladina czy w/e i nie wiem jak przejść od wyboru usera do połączenia tego z enumem. Jak to jest robione? Ktoś wprowadza do programu string, a my na podstawie tego decydujemy jaki obiekt zwracamy, czy inaczej się to odbywa? Jak w takim razie od stringa przejść na (enum) WarriorType.PALADIN na ten przykład.

4. Factory Method od Simple Factory Pattern różni się tym, że jest klasa abstrakcyjna po której dziedziczy nasza konkretna fabryka i rozumiem, że to ma sens tylko wtedy jeżeli wykonujemy dla każdego obiektu zwracanego jakieś powtarzające się akcje przykład pizzy gdzie po zwróceniu jej każdą jedną trzeba zapakować i wtedy to trafia do abstrakcyjnej klasy? Bo w innym wypadku i jedno i drugie wydaje im się identyczne i gdy potrzebujemy przenieść logikę zwracania samych obiektów wystarczy Simple Factory.

Wiem, że 3 i 4 pytanie trochę zamieszałem, ale.. trudno mi ubrać w słowa to czego nie wiem. Przeczytałem chyba pół tuzina artykułów na ten temat, więc będę wdzięczny za wszysto co przybliży mnie do zrozumienia w/w rzeczy :)

1

Oba sposoby są dobre. Drugi jest ciekawszy i bardziej elastyczny. Oczywiście zamiast stringów operuje się na enumie :)

0

A jak wygląda taka "operacja"? Załóżmy, całkiem abstrakcyjnie, że user klika button, żeby wybrać postać. Ja znam dwie możliwości. Informacja o kliknięciu może zawierać string np. "Rogue" albo ID 11 odpowiadający jakiemuś stringowi (do tej pory nauczono mnie, że trzyma się w bazie na zasadzie ID => name, co w praktyce jest troche poronione). Nie mam zielonego pojęcia jak taki typ danych powiązać z enumem, inaczej jak wybrać enum (WarriotType.CoTutaj?) na podstawie inputu usera. No bo skoro mam w metodzie wprowadzić enum to chyba jakoś muszę wybrać odpowiedni w zależności co wybral user :)

0

User klika button, a w enumie robisz metodę "fromString" lub "fromButtonId", która zwraca konkretnego enuma. Robisz to na samej "górze" aplikacji.
Np. WarriorType.fromString("PALADIN");

Przykładowa implementacja:

public enum Warrior {
    PALADIN,
    ROGUE;

    public Warrior fromString(final String name) {
        switch (name.toLowerCase()) {
        case "paladin": {
            return Warrior.PALADIN;
        }
        case "rogue": {
            return Warrior.ROGUE;
        }
        default:
            throw new IllegalArgumentException("Not recognized");
        }
    }

}
1

Oczywiście można napisać taką metodę ale enum posiada już metodę valueOf która działa tak samo jak ta podana wyżej, z różnicą, że jest case sensitive.

1 użytkowników online, w tym zalogowanych: 0, gości: 1