W weekend pisałem trochę kodu i chciałem napisać fabrykę jako metodę statyczną w klasie bazowej.
Moim pytaniem jest po prostu wiedzieć, czy jest to podejście idomatyczne?
Wydaje mi się, że może nie być tak, że klasa podstawowa ma wiedzę o klasie pochodnej.
To powiedziawszy, nie jestem pewien prostszego sposobu na uzyskanie tego samego rezultatu. Cała inna klasa fabryczna wydaje mi się (przynajmniej dla mnie) niepotrzebną złożonością (?)
Coś jak:
class Animal
{
public static Animal CreateAnimal(string name)
{
switch(name)
{
case "Shark":
return new SeaAnimal();
break;
case "Dog":
return new LandAnimal();
break;
default:
throw new Exception("unknown animal");
}
}
}
class LandAnimal : Animal
{
}
class SeaAnimal : Animal
{
}
c#
class-design
Aaron Anodide
źródło
źródło
Odpowiedzi:
Zaletą oddzielnej klasy fabrycznej jest to, że można ją wyśmiewać w testach jednostkowych.
Ale jeśli nie zamierzasz tego robić lub uczynić go polimorficznym w jakikolwiek inny sposób, to statyczna metoda Factory na samej klasie jest OK.
źródło
Możesz użyć Generics, aby uniknąć instrukcji switch i oddzielić późniejsze implementacje od klasy podstawowej:
Stosowanie:
lub
źródło
Podsumowując, fabryka może być również ogólna.
Następnie można stworzyć dowolną fabrykę obiektów, która z kolei mogłaby stworzyć dowolny typ obiektu. Nie jestem pewien, czy jest to prostsze, z pewnością bardziej ogólne.
Nie widzę nic złego w instrukcji switch dla małej implementacji fabrycznej. Gdy przejdziesz do dużej liczby obiektów lub możliwych różnych hierarchii klas, myślę, że bardziej ogólne podejście jest bardziej odpowiednie.
źródło
Kiepski pomysł. Po pierwsze, narusza zasadę otwartego zamknięcia. W przypadku każdego nowego zwierzęcia musiałbyś znów zadzierać z klasą podstawową i potencjalnie byś go złamał. Zależności pójdą w złą stronę.
Jeśli musisz stworzyć zwierzęta z konfiguracji, taka konstrukcja byłaby w porządku, chociaż lepszym rozwiązaniem byłoby użycie refleksji w celu uzyskania typu pasującego do nazwy i utworzenia go za pomocą uzyskanej informacji o typie.
Ale powinieneś utworzyć dedykowaną klasę fabryczną, niezwiązaną z hierarchią klas zwierząt, i zwrócić interfejs IAnimal zamiast typu podstawowego. Wtedy przydałoby się, osiągnęlibyście pewne oddzielenie.
źródło
To pytanie jest dla mnie aktualne - wczoraj pisałem prawie dokładnie taki kod. Po prostu zamień „Animal” na wszystko, co jest istotne w moim projekcie, chociaż pozostanę przy „Animal” w celu omówienia tutaj. Zamiast instrukcji „switch” miałem nieco bardziej złożoną serię instrukcji „if”, obejmującą więcej niż tylko porównanie jednej zmiennej z pewnymi ustalonymi wartościami. Ale to szczegół. Statyczna metoda fabryczna wydawała się zgrabnym sposobem projektowania rzeczy, ponieważ projekt powstał z refaktoryzacji wcześniejszych, szybkich i brudnych elementów kodu.
Odrzuciłem ten projekt ze względu na klasę podstawową mającą wiedzę o klasie pochodnej. Jeśli klasy LandAnimal i SeaAnimal są małe, czyste i łatwe, mogą znajdować się w tym samym pliku źródłowym. Ale mam duże niechlujne metody odczytu plików tekstowych niezgodnych z żadnymi oficjalnie zdefiniowanymi standardami - chcę, aby moja klasa LandAnimal miała własny plik źródłowy.
Prowadzi to do zależności plików cyklicznych - LandAnimal pochodzi od Animal, ale Animal musi już wiedzieć, że istnieje LandAnimal, SeaAnimal i piętnaście innych klas. Wyciągnąłem metodę fabryczną, umieściłem ją we własnym pliku (w mojej głównej aplikacji, a nie w bibliotece Animals) Posiadanie statycznej metody fabrycznej wydawało się urocze i sprytne, ale zdałem sobie sprawę, że tak naprawdę nie rozwiązało to żadnego problemu projektowego.
Nie mam pojęcia, jak to się ma do idiomatycznego C #, ponieważ często zmieniam języki, zwykle ignoruję idiomy i konwencje specyficzne dla języków i stosy deweloperów poza moją zwykłą pracą. Jeśli cokolwiek, mój C # może wyglądać „pytonicznie”, jeśli to ma sens. Dążę do ogólnej jasności.
Nie wiem też, czy przydałoby się stosowanie statycznej metody fabrycznej w przypadku małych, prostych klas, które raczej nie zostaną rozszerzone w przyszłości - posiadanie tego wszystkiego w jednym pliku źródłowym może być przyjemne w niektórych przypadkach.
źródło