Niedawno usunąłem moją odpowiedź Java w Code Review , która zaczęła się tak:
private Person(PersonBuilder builder) {
Zatrzymać. Czerwona flaga. Osoba budująca osobę zbuduje osobę; wie o Osobie. Klasa Person nie powinna wiedzieć nic o PersonBuilder - to tylko niezmienny typ. Utworzyłeś tutaj sprzęgło kołowe, w którym A zależy od B, który zależy od A.
Osoba powinna po prostu przyjąć swoje parametry; klient, który chce stworzyć Osobę bez budowania, powinien móc to zrobić.
Zostałem uderzony w głos głosowania i powiedziałem (cytując) czerwoną flagę, dlaczego? Implementacja ma ten sam kształt, co Joshua Bloch zademonstrował w swojej książce „Effective Java” (punkt # 2).
Wygląda więc na to, że jedynym słusznym sposobem implementacji wzorca konstruktora w Javie jest uczynienie konstruktora typem zagnieżdżonym (nie o to chodzi w tym pytaniu), a następnie uczynienie produktu (klasa budowanego obiektu ) weź zależność od konstruktora , na przykład:
private StreetMap(Builder builder) { // Required parameters origin = builder.origin; destination = builder.destination; // Optional parameters waterColor = builder.waterColor; landColor = builder.landColor; highTrafficColor = builder.highTrafficColor; mediumTrafficColor = builder.mediumTrafficColor; lowTrafficColor = builder.lowTrafficColor; }
Ta sama strona Wikipedii dla tego samego wzorca Konstruktora ma zupełnie inną (i znacznie bardziej elastyczną) implementację dla C #:
//Represents a product created by the builder public class Car { public Car() { } public int Wheels { get; set; } public string Colour { get; set; } }
Jak widać, produkt tutaj nie wie nic o Builder
klasie, a wszystko, co go obchodzi, może zostać utworzony przez bezpośrednie wywołanie konstruktora, fabrykę abstrakcyjną ... lub konstruktora - o ile rozumiem, produkt o twórczym wzorze nigdy nie musi wiedzieć nic o tym, co go tworzy.
Dostałem kontrargument (który najwyraźniej jest wyraźnie broniony w książce Blocha), że wzorzec konstruktora mógłby zostać użyty do przerobienia typu, który miałby rozdęty konstruktor z dziesiątkami opcjonalnych argumentów. Zamiast więc trzymać się tego, co myślałem , że trochę przestudiowałem na tej stronie, i odkryłem, że jak podejrzewałem, ten argument nie dotyczy wody .
Więc o co chodzi? Po co wymyślać zbyt skomplikowane rozwiązania problemu, który w ogóle nie powinien istnieć? Jeśli na chwilę zdejmiemy Joshua Blocha z piedestału, czy możemy wymyślić jeden dobry, ważny powód, aby połączyć dwa konkretne typy i nazwać to najlepszą praktyką?
To wszystko cuchnie programowaniu kultu .