Dlaczego powinienem używać klasy fabrycznej zamiast bezpośredniej konstrukcji obiektu?

162

Widziałem historię kilku projektów bibliotek klas С # i Java na GitHub i CodePlex, i widzę trend przechodzenia do klas fabrycznych w przeciwieństwie do bezpośredniego tworzenia instancji obiektów.

Dlaczego powinienem intensywnie korzystać z klas fabrycznych? Mam całkiem niezłą bibliotekę, w której obiekty są tworzone w staromodny sposób - przy użyciu publicznych konstruktorów klas. W ostatnich aktach autorzy szybko zmienili wszystkich publicznych konstruktorów tysięcy klas na wewnętrzne, a także stworzyli jedną ogromną klasę fabryczną z tysiącami CreateXXXmetod statycznych, które tylko zwracają nowe obiekty przez wywołanie wewnętrznych konstruktorów klas. Zewnętrzny interfejs API projektu jest uszkodzony, dobra robota.

Dlaczego taka zmiana byłaby przydatna? Jaki jest sens refaktoryzacji w ten sposób? Jakie są zalety zastąpienia wywołań konstruktorów klasy publicznej wywołaniami metod statycznych?

Kiedy powinienem używać publicznych konstruktorów, a kiedy powinienem używać fabryk?

rufanov
źródło
1
Jaka jest klasa / metoda tkaniny?
Doval

Odpowiedzi:

56

Klasy fabryczne są często wdrażane, ponieważ pozwalają projektowi ściślej przestrzegać zasad SOLID . W szczególności zasady segregacji interfejsów i zasady inwersji zależności.

Fabryki i interfejsy pozwalają na znacznie bardziej długoterminową elastyczność. Pozwala to na bardziej niezależny - a zatem i bardziej testowalny - projekt. Oto niewyczerpująca lista powodów, dla których możesz pójść tą ścieżką:

  • Umożliwia łatwe wprowadzenie kontenera Inversion of Control (IoC)
  • Dzięki temu kod jest bardziej testowalny, ponieważ można wyśmiewać interfejsy
  • Daje to o wiele większą elastyczność, gdy przychodzi czas na zmianę aplikacji (tzn. Możesz tworzyć nowe implementacje bez zmiany zależnego kodu)

Rozważ tę sytuację.

Zespół A (-> środki zależą od):

Class A -> Class B
Class A -> Class C
Class B -> Class D

Chcę przenieść klasę B do zestawu B, który jest zależny od zestawu A. Z tymi konkretnymi zależnościami muszę przenieść większość całej mojej hierarchii klas. Jeśli użyję interfejsów, mogę uniknąć dużego bólu.

Montaż A:

Class A -> Interface IB
Class A -> Interface IC
Class B -> Interface IB
Class C -> Interface IC
Class B -> Interface ID
Class D -> Interface ID

Teraz mogę przenieść klasę B do zestawu B bez żadnego bólu. Nadal zależy to od interfejsów w zestawie A.

Korzystanie z kontenera IoC w celu rozwiązania zależności pozwala na jeszcze większą elastyczność. Nie ma potrzeby aktualizowania każdego wywołania do konstruktora za każdym razem, gdy zmieniasz zależności klasy.

Przestrzeganie zasady segregacji interfejsu i zasady inwersji zależności pozwala nam budować wysoce elastyczne, oddzielone od siebie aplikacje. Po opracowaniu aplikacji tego typu nigdy więcej nie będziesz chciał wrócić do używania newsłowa kluczowego.

Stephen
źródło
40
Fabryki IMO są najmniej ważne dla SOLID. Możesz robić SOLID dobrze bez fabryk.
Euforyczny
26
Jedną rzeczą, która nigdy nie miała dla mnie sensu jest to, że jeśli używasz fabryk do tworzenia nowych obiektów, musisz przede wszystkim zbudować fabrykę. Co to w takim razie daje? Czy zakłada się, że ktoś inny da ci fabrykę zamiast tworzyć ją samodzielnie, czy coś innego? Należy o tym wspomnieć w odpowiedzi, w przeciwnym razie nie jest jasne, w jaki sposób fabryki faktycznie rozwiązują każdy problem.
Mehrdad
8
@ BЈовић - Za wyjątkiem tego, że za każdym razem, gdy dodajesz nową implementację, możesz teraz otworzyć fabrykę i zmodyfikować ją, aby uwzględnić nową implementację - jawnie naruszając OCP.
Telastyn
6
@Telastyn Tak, ale kod używający utworzonych obiektów nie ulega zmianie. Jest to ważniejsze niż zmiany w fabryce.
BЈовић
8
Fabryki są przydatne w niektórych obszarach, których dotyczy odpowiedź. Nie są odpowiednie do stosowania wszędzie . Na przykład używanie fabryk do tworzenia ciągów lub list byłoby zbyt daleko posunięte. Nawet w przypadku UDT nie zawsze są one konieczne. Kluczem jest skorzystanie z fabryki, gdy konieczne jest oddzielenie dokładnej implementacji interfejsu.
126

Jak powiedział whatsisname , uważam, że jest to przypadek projektowania oprogramowania kultowego . Fabryki, szczególnie abstrakcyjne, są użyteczne tylko wtedy, gdy moduł tworzy wiele instancji klasy, a użytkownik chce dać użytkownikowi tego modułu możliwość określenia, który typ ma zostać utworzony. To wymaganie jest w rzeczywistości dość rzadkie, ponieważ przez większość czasu potrzebujesz tylko jednej instancji i możesz ją przekazać bezpośrednio zamiast tworzyć jawną fabrykę.

Chodzi o to, że fabryki (i singletony) są niezwykle łatwe do wdrożenia, więc ludzie często z nich korzystają, nawet w miejscach, gdzie nie są konieczne. Więc kiedy programista myśli „Jakie wzorce projektowe powinienem zastosować w tym kodzie?” Fabryka jako pierwsza przychodzi mu na myśl.

Wiele fabryk powstaje, ponieważ „Może kiedyś będę musiał stworzyć te klasy inaczej”. Co jest wyraźnym naruszeniem YAGNI .

A fabryki stają się przestarzałe po wprowadzeniu frameworka IoC, ponieważ IoC jest tylko rodzajem fabryki. I wiele platform IoC jest w stanie tworzyć implementacje określonych fabryk.

Ponadto nie ma wzorca projektowego, który mówi o tworzeniu ogromnych klas statycznych za pomocą CreateXXXmetod wywołujących tylko konstruktory. I nie jest to szczególnie nazywane Fabryką (ani Fabryką Abstrakcyjną).

Euforyk
źródło
6
Zgadzam się z większością twoich argumentów, z wyjątkiem tego, że „IoC jest rodzajem fabryki” : pojemniki IoC niefabrykami . Są wygodną metodą uzyskania zastrzyku zależności. Tak, niektóre są zdolne do budowy automatycznych fabryk, ale same nie są fabrykami i nie powinny być traktowane jako takie. Chciałbym również walczyć o punkt YAGNI. Przydaje się możliwość zastąpienia podwójnego testu w teście jednostkowym. Refaktoryzacja wszystkiego, aby to zapewnić po fakcie, jest bolesna w tyłek . Planuj z wyprzedzeniem i nie daj się nabrać na wymówkę „YAGNI”
AlexFoxGill
11
@AlexG - eh ... w praktyce prawie wszystkie kontenery IoC działają jak fabryki.
Telastyn
8
@AlexG Głównym celem IoC jest konstruowanie konkretnych obiektów do przechodzenia do innych obiektów w oparciu o konfigurację / konwencję. To jest to samo, co przy użyciu fabryki. I nie potrzebujesz fabryki, aby móc stworzyć próbną próbę. Po prostu tworzysz instancję i przekazujesz próbę bezpośrednio. Tak jak powiedziałem w pierwszym akapicie. Fabryki są przydatne tylko wtedy, gdy użytkownik chce przekazać utworzenie instancji użytkownikowi modułu, który wywołuje fabrykę.
Euforia
5
Należy wprowadzić rozróżnienie. Wzór fabryki jest wykorzystywany przez konsumentów do tworzenia jednostek w trakcie wykonywania programu. Pojemnik IoC służy do utworzenia wykresu przedmiot programu podczas rozruchu. Możesz to zrobić ręcznie, pojemnik jest tylko wygodą. Konsument fabryki nie powinien wiedzieć o pojemniku IoC.
AlexFoxGill
5
Odp: „I nie potrzebujesz fabryki, aby móc stworzyć próbkę do testu. Po prostu utwórz instancję i zdaj próbę bezpośrednio” - znowu, różne okoliczności. Korzystasz z fabryki, aby poprosić o instancję - konsument kontroluje tę interakcję. Podanie instancji przez konstruktor lub metodę nie działa, to inny scenariusz.
AlexFoxGill
79

Moda na wzorce fabryczne wynika z niemal dogmatycznego przekonania programistów w językach „C” (C / C ++, C #, Java), że użycie słowa kluczowego „new” jest złe i należy go unikać za wszelką cenę (lub najmniej scentralizowany). To z kolei wynika z bardzo ścisłej interpretacji zasady pojedynczej odpowiedzialności („S” SOLID), a także zasady inwersji zależności („D”). Mówiąc wprost, SRP mówi, że idealnie obiekt kodu powinien mieć jeden „powód do zmiany” i tylko jeden; ten „powód zmiany” jest głównym celem tego obiektu, jego „odpowiedzialnością” w bazie kodu i wszystko, co wymaga zmiany kodu, nie powinno wymagać otwarcia tego pliku klasy. DIP jest jeszcze prostszy; obiekt kodu nigdy nie powinien być zależny od innego konkretnego obiektu,

W tym przypadku, używając „new” i konstruktora publicznego, podłączasz kod wywołujący do konkretnej metody konstrukcyjnej określonej konkretnej klasy. Twój kod musi teraz wiedzieć, że istnieje klasa MyFooObject i ma konstruktor, który pobiera ciąg i liczbę całkowitą. Jeśli ten konstruktor kiedykolwiek potrzebuje więcej informacji, wszystkie zastosowania konstruktora muszą zostać zaktualizowane, aby przekazać te informacje, w tym te, które piszesz teraz, a zatem muszą mieć coś ważnego do przekazania, więc muszą albo lub zmień, aby go zdobyć (dodając więcej obowiązków do zużywających się obiektów). Ponadto, jeśli MyFooObject zostanie kiedykolwiek zastąpiony w bazie kodu przez BetterFooObject, wszystkie zastosowania starej klasy muszą się zmienić, aby zbudować nowy obiekt zamiast starego.

Zamiast tego wszyscy konsumenci MyFooObject powinni być bezpośrednio zależni od „IFooObject”, który określa zachowanie klas implementujących, w tym MyFooObject. Teraz konsumenci IFooObjects nie mogą po prostu zbudować IFooObject (bez wiedzy, że konkretna konkretna klasa jest IFooObject, której nie potrzebują), dlatego zamiast tego muszą otrzymać instancję klasy lub metody implementującej IFooObject z zewnątrz, przez inny obiekt, który ma obowiązek wiedzieć, jak stworzyć właściwy obiekt IFooObject na okoliczność, która w naszym języku jest zwykle znana jako Fabryka.

Tutaj teoria spotyka się z rzeczywistością; obiekt nigdy nie może być cały czas zamknięty na wszystkie rodzaje zmian. W tym przypadku IFooObject jest teraz dodatkowym obiektem kodu w bazie kodu, który musi się zmieniać za każdym razem, gdy zmieni się interfejs wymagany przez konsumentów lub implementacje IFooObjects. Wprowadza to nowy poziom złożoności związany ze zmianą sposobu interakcji obiektów między sobą w ramach tej abstrakcji. Ponadto konsumenci nadal będą musieli się zmienić i głębiej, jeśli sam interfejs zostanie zastąpiony nowym.

Dobry programista wie, jak zrównoważyć YAGNI („Nie będziesz go potrzebował”) z SOLID, analizując projekt i znajdując miejsca, które najprawdopodobniej będą musiały się zmienić w określony sposób, i przefaktoryzuj je, aby były bardziej tolerancyjne na tego typu zmiany, ponieważ w tym przypadku „ty to będzie to potrzebne”.

KeithS
źródło
21
Uwielbiam tę odpowiedź, szczególnie po przeczytaniu wszystkich innych. Mogę dodać, że prawie wszyscy (dobrzy) nowi koderzy są zbyt dogmatyczni w stosunku do zasad przez prosty fakt, że naprawdę chcą być dobrzy, ale jeszcze nie nauczyli się wartości prostoty i nie przesadzają.
jean
1
Innym problemem związanym z konstruktorami publicznymi jest to, że nie ma dobrego sposobu, aby klasa Foookreśliła konstruktora publicznego, który powinien być użyteczny do tworzenia Fooinstancji lub tworzenia innych typów w ramach tego samego pakietu / zestawu , ale nie powinien być przydatny do tworzenia typy wyprowadzone gdzie indziej. Nie znam żadnego szczególnie ważnego powodu, dla którego język / środowisko nie mogło zdefiniować osobnych konstruktorów do użycia w newwyrażeniach, w przeciwieństwie do wywoływania z konstruktorów podtypów, ale nie znam żadnych języków, które to odróżniają.
supercat
1
Takim sygnałem byłby chroniony i / lub wewnętrzny konstruktor; ten konstruktor byłby dostępny tylko do konsumpcji kodu w podklasie lub w tym samym zestawie. C # nie ma kombinacji słów kluczowych dla „chronionego i wewnętrznego”, co oznacza, że ​​mogą z niego korzystać tylko podtypy w zestawie, ale MSIL ma identyfikator zakresu dla tego rodzaju widoczności, więc można sobie wyobrazić, że specyfikacja C # może zostać rozszerzona, aby zapewnić sposób na wykorzystanie go . Ale tak naprawdę nie ma to wiele wspólnego z korzystaniem z fabryk (chyba że skorzystasz z ograniczenia widoczności, aby wymusić korzystanie z fabryki).
KeithS
2
Idealna odpowiedź. Tuż w punkcie „teoria spotyka rzeczywistość”. Wystarczy pomyśleć o tym, ile tysięcy programistów i ludzi poświęcało kult ładunków, chwaląc, usprawiedliwiając, wdrażając, wykorzystując ich do tego, by potem wpadli w tę samą sytuację, którą opisaliście, jest po prostu szalone. Po YAGNI nigdy nie zauważyłem potrzeby wdrożenia fabryki
Breno Salgado,
Programuję na bazie kodu, ponieważ ponieważ implementacja OOP nie pozwala na przeciążanie konstruktora, użycie publicznych konstruktorów jest skutecznie zakazane. Jest to już niewielki problem w językach, które na to pozwalają. Jak stworzyć temperaturę. Zarówno Fahrenheit, jak i Celsjusz są zmiennoprzecinkowe. Możesz je jednak zapakować, a następnie rozwiązać problem.
jgmjgm
33

Konstruktory są w porządku, jeśli zawierają krótki, prosty kod.

Gdy inicjalizacja staje się czymś więcej niż przypisywaniem kilku zmiennych do pól, fabryka ma sens. Oto niektóre z korzyści:

  • Długi, skomplikowany kod ma większy sens w dedykowanej klasie (fabryce). Jeśli ten sam kod zostanie wstawiony do konstruktora, który wywołuje kilka metod statycznych, spowoduje to zanieczyszczenie głównej klasy.

  • W niektórych językach i niektórych przypadkach zgłaszanie wyjątków w konstruktorach jest naprawdę złym pomysłem , ponieważ może wprowadzać błędy.

  • Podczas wywoływania konstruktora użytkownik wywołujący musi znać dokładny typ instancji, którą chcesz utworzyć. Nie zawsze tak jest ( Feederpo prostu muszę je zbudować Animal, aby je nakarmić; nie dbam o to, czy jest to Doga Cat).

Arseni Mourzenko
źródło
2
Dostępne opcje to nie tylko „fabryka” lub „konstruktor”. A Feedermoże użyć żadnego z nich i zamiast tego wywołać metodę Kennelobiektu getHungryAnimal.
DougM
4
+1 Uważam, że przestrzeganie zasady absolutnej braku logiki w konstruktorze nie jest złym pomysłem. Konstruktor powinien być używany tylko do ustawiania stanu początkowego obiektu poprzez przypisanie jego wartości argumentów do zmiennych instancji. Jeśli potrzebne jest coś bardziej skomplikowanego, przynajmniej stwórz fabryczną (klasową) metodę budowy instancji.
KaptajnKold
To jedyna satysfakcjonująca odpowiedź, jaką tu widziałem, uratowała mnie przed koniecznością pisania własnych. Pozostałe odpowiedzi dotyczą wyłącznie pojęć abstrakcyjnych.
TheCatWhisperer
Ale ten argument można również uznać za prawdziwy Builder Pattern. Czyż nie
soufrk
Konstruktorzy rządzą
Breno Salgado,
10

Jeśli pracujesz z interfejsami, możesz pozostać niezależny od faktycznej implementacji. Fabrykę można skonfigurować (za pomocą właściwości, parametrów lub innej metody), aby utworzyć instancję jednego z wielu różnych wdrożeń.

Jeden prosty przykład: chcesz komunikować się z urządzeniem, ale nie wiesz, czy będzie to przez Ethernet, COM czy USB. Definiujesz jeden interfejs i 3 implementacje. W czasie wykonywania możesz następnie wybrać metodę, którą chcesz, a fabryka zapewni odpowiednią implementację.

Używaj go często ...

Paweł
źródło
5
Dodałbym, że świetnie jest go używać, gdy istnieje wiele implementacji interfejsu, a kod wywołujący nie wie lub nie powinien wiedzieć, który wybrać. Ale gdy metoda fabrycznym jest po prostu statycznych otoki wokół jednego konstruktora jak w pytaniu, że jest anty-wzór. Do wyboru musi być wiele wdrożeń, w przeciwnym razie fabryka przeszkadza i dodaje niepotrzebnej złożoności.
Teraz masz dodatkową elastyczność i teoretycznie Twoja aplikacja może korzystać z Ethernetu, COM, USB i portu szeregowego, jest teoretycznie gotowa na fireloop lub cokolwiek. W rzeczywistości Twoja aplikacja będzie komunikować się tylko przez Ethernet ... zawsze.
Pieter B
7

Jest to objaw ograniczenia w systemach modułowych Java / C #.

Zasadniczo nie ma powodu, dla którego nie powinieneś być w stanie zamienić jednej implementacji klasy na inną z tym samym sygnaturą konstruktora i metody. Tam języki, które pozwalają na to. Jednak Java i C # nalegają, aby każda klasa miała unikalny identyfikator (w pełni kwalifikowaną nazwę), a kod klienta kończy się na niej mocno zakodowaną zależnością.

Można rodzaj obejść ten problem przez majstrowanie przy użyciu systemu plików i opcje kompilatora, dzięki czemu com.example.Foomapy do innego pliku, ale to jest zaskakujące i nieintuicyjne. Nawet jeśli to zrobisz, Twój kod jest nadal powiązany tylko z jedną implementacją klasy. Tzn. Jeśli napiszesz klasę Foozależną od klasy MySet, możesz wybrać implementację MySetw czasie kompilacji, ale nadal nie możesz utworzyć instancji Fooza pomocą dwóch różnych implementacji MySet.

Ta niefortunna decyzja projektowa zmusza ludzi do interfaceniepotrzebnego wykorzystywania s, aby zabezpieczyć swój kod na przyszłość przed możliwością, że będą później potrzebować innej implementacji lub ułatwić testowanie jednostek. Nie zawsze jest to możliwe; jeśli masz jakieś metody, które sprawdzają prywatne pola dwóch instancji klasy, nie będziesz w stanie zaimplementować ich w interfejsie. Dlatego na przykład nie widzisz unionw Setinterfejsie Java . Mimo to, poza typami liczbowymi i kolekcjami, metody binarne nie są powszechne, więc zwykle można się z tym pogodzić.

Oczywiście, jeśli zadzwonisz new Foo(...), nadal będziesz zależny od klasy , więc potrzebujesz fabryki, jeśli chcesz, aby klasa mogła bezpośrednio utworzyć interfejs. Jednak zwykle lepszym pomysłem jest zaakceptowanie instancji w konstruktorze i pozwolenie komuś innemu decydować, której implementacji użyć.

Od Ciebie zależy, czy warto rozbudować bazę kodową interfejsami i fabrykami. Z jednej strony, jeśli dana klasa jest wewnętrzną bazą kodu, refaktoryzacja kodu w taki sposób, aby używał innej klasy lub interfejsu w przyszłości, jest banalna; jeśli sytuacja się pojawi, możesz skorzystać z YAGNI i dokonać refaktora później. Ale jeśli klasa jest częścią publicznego interfejsu API opublikowanej biblioteki, nie ma możliwości poprawienia kodu klienta. Jeśli nie używasz, interfacea później potrzebujesz wielu implementacji, utkniesz między skałą a trudnym miejscem.

Doval
źródło
2
Chciałbym, aby Java i pochodne, takie jak .NET, miały specjalną składnię dla klasy tworzącej własne instancje, a poza tym newbyłyby po prostu cukrem syntaktycznym do wywoływania specjalnie nazwanej metody statycznej (która byłaby generowana automatycznie, gdyby typ miał „publiczny konstruktor” ”, ale nie zawiera jawnie metody). IMHO, jeśli kod chce tylko nudnej domyślnej rzeczy, która się implementuje List, powinien mieć możliwość nadania jej interfejsu bez konieczności posiadania przez klienta wiedzy o konkretnej implementacji (np ArrayList.).
supercat
2

Moim zdaniem po prostu używają Prostej Fabryki, która nie jest właściwym wzorcem projektowym i nie powinna być mylona z Fabryką Abstrakcyjną lub Metodą Fabryczną.

A ponieważ stworzyli „ogromną klasę tkanin z tysiącami statycznych metod CreateXXX”, brzmi to anty-wzór (może klasa Boga?).

Myślę, że Proste fabryki i metody tworzenia statycznego (które nie wymagają klasy zewnętrznej) mogą być przydatne w niektórych przypadkach. Na przykład, gdy konstrukcja obiektu wymaga różnych kroków, takich jak tworzenie innych obiektów (np. Preferowanie kompozycji).

Nie nazwałbym nawet tego, że to Fabryka, ale tylko kilka metod zawartych w losowej klasie z sufiksem „Fabryka”.

FranMowinckel
źródło
1
Simple Factory ma swoje miejsce. Wyobraź sobie, że jednostka bierze dwa parametry konstruktora, int xi IFooService fooService. Nie chcesz fooServicewszędzie chodzić , więc tworzysz fabrykę metodą Create(int x)i wstrzykujesz usługę wewnątrz fabryki.
AlexFoxGill
4
@AlexG A potem musisz IFactorywszędzie krążyć wokół IFooService.
Euforia
3
Zgadzam się z euforią; z mojego doświadczenia wynika, że ​​obiekty, które są wstrzykiwane do wykresu od góry, zwykle są typu, którego potrzebują wszystkie obiekty niższego poziomu, więc przekazywanie IFooServices nie jest niczym wielkim. Zastąpienie jednej abstrakcji inną nie prowadzi do niczego poza dalszym zaciemnianiem bazy kodu.
KeithS
wydaje się to całkowicie nieistotne dla pytania: „Dlaczego powinienem używać klasy fabrycznej zamiast bezpośredniej budowy obiektów? Kiedy powinienem używać publicznych konstruktorów, a kiedy powinienem używać fabryk?” Zobacz, jak odpowiedzieć
gnat,
1
To tylko tytuł pytania, myślę, że przegapiłeś resztę. Zobacz ostatni punkt podanego linku;).
FranMowinckel,
1

Jako użytkownik biblioteki, jeśli biblioteka ma metody fabryczne, powinieneś ich użyć. Zakłada się, że metoda fabryczna daje autorowi biblioteki elastyczność w zakresie wprowadzania pewnych zmian bez wpływu na kod. Mogą na przykład zwrócić instancję jakiejś podklasy w metodzie fabrycznej, która nie działałaby z prostym konstruktorem.

Jako twórca biblioteki używałbyś metod fabrycznych, jeśli sam chciałbyś skorzystać z tej elastyczności.

W opisanym przypadku masz wrażenie, że zastąpienie konstruktorów metodami fabrycznymi było po prostu bezcelowe. Z pewnością był to ból dla wszystkich zaangażowanych; biblioteka nie powinna niczego usuwać z interfejsu API bez bardzo ważnego powodu. Gdybym więc dodał metody fabryczne, pozostawiłbym dostępne konstruktory, być może przestarzałe, dopóki metoda fabryczna nie wywoła już więcej tego konstruktora, a kod używający zwykłego konstruktora działa gorzej niż powinien. Twoje wrażenie może mieć rację.

gnasher729
źródło
Uwaga: Jeśli programista musi zapewnić klasę pochodną z dodatkową funkcjonalnością (dodatkowe właściwości, inicjalizacja), może to zrobić. (zakładając, że metody fabryczne są nadrzędne). Autor interfejsu API może również obejść specjalne potrzeby klienta.
Eric Schneider,
-4

Wydaje się to być przestarzałe w dobie Scali i programowania funkcjonalnego. Solidny fundament funkcji zastępuje klasy gazillionów.

Należy również zauważyć, że podwójne Java {{nie działa już w przypadku korzystania z fabryki, tj

someFunction(new someObject() {{
    setSomeParam(...);
    etc..
}})

Co pozwoli ci stworzyć anonimową klasę i ją dostosować.

W przypadku dylematu przestrzeni czasowej czynnik czasu jest teraz tak bardzo zmniejszony dzięki szybkim procesorom, że funkcjonalne programowanie umożliwiające zmniejszenie przestrzeni, tj. Rozmiar kodu, jest teraz praktyczne.

Marc
źródło
2
wygląda to bardziej na komentarz styczny (patrz Jak odpowiedzieć ) i nie wydaje się, aby zapewniało coś istotnego w porównaniu z punktami przedstawionymi i wyjaśnionymi w poprzednich 9 odpowiedziach
gnat,