Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
translation

To jest post przetłumaczony przez AI.

제이온

[Efektywny Java] Punkt 2. Jeśli konstruktor ma wiele parametrów, rozważ użycie buildera

  • Język pisania: Koreański
  • Kraj referencyjny: Wszystkie kraje country-flag

Wybierz język

  • Polski
  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Nederlands
  • हिन्दी
  • Magyar

Tekst podsumowany przez sztuczną inteligencję durumis

  • Prezentuje różne wzorce służące do efektywnego zarządzania konstruktorami z wieloma parametrami, porównując zalety i wady wzorca konstruktora stopniowego, wzorca fasoli Java i wzorca buildera.
  • Wzorzec buildera ma tę zaletę, że zwiększa czytelność i stabilność kodu, a jego użycie jest szczególnie efektywne w przypadku klas zaprojektowanych hierarchicznie.
  • Wzorzec buildera pozwala na bardziej przejrzyste pisanie kodu, ale ma wadę w postaci tworzenia obiektu buildera i zwiększania rozwleklego charakteru kodu.

Wzór projektowy budowniczego

Zarówno statyczne fabryki, jak i konstruktory mają problemy z obsługą dużej liczby parametrów. Na przykład, jeśli klasa ma 6 pól i chcemy utworzyć konstruktor dla 2 parametrów, 3 parametrów itd., możemy wykorzystać wzorzec projektowy budowniczego, jak pokazano poniżej.


public class NutritionFacts {

    private final int servingSize;

    private final int servings;

    private final int calories;

    private final int fat;

    private final int sodium;

    private final int carbohydrate;

    public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) {
        this.servingSize = servingSize;
        this.servings = servings;
        this.calories = calories;
        this.fat = fat;
        this.sodium = sodium;
        this.carbohydrate = carbohydrate;
    }

    public NutritionFacts(int servingSize, int servings) {
        this(servingSize, servings, 0, 0, 0, 0);
    }

    public NutritionFacts(int servingSize, int servings, int calories) {
        this(servingSize, servings, calories, 0, 0, 0);
    }

    public NutritionFacts(int servingSize, int servings, int calories, int fat) {
        this(servingSize, servings, calories, fat, 0, 0);
    }

    public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium) {
        this(servingSize, servings, calories, fat, sodium, 0);
    }


Jednak nawet w tym przypadku, gdy liczba parametrów jest duża, kod może być trudny do odczytania, a wartości parametrów mogą być mylące, zwłaszcza gdy parametry mają ten sam typ.


Wzorzec projektowy JavaBeans

Wzorzec projektowy JavaBeans polega na tworzeniu obiektu za pomocą konstruktora bez parametrów, a następnie ustawianiu wartości żądanych parametrów za pomocą metod setter.


public class NutritionFactsWithJavaBeansPattern {

    private int servingSize = -1; // wymagane. Brak wartości domyślnej.

    private int servings = -1; // wymagane. Brak wartości domyślnej.

    private int calories;

    private int fat;

    private int sodium;

    private int carbohydrate;

    public void setServingSize(int servingSize) {
        this.servingSize = servingSize;
    }

    public void setServings(int servings) {
        this.servings = servings;
    }

    public void setCalories(int calories) {
        this.calories = calories;
    }

    public void setFat(int fat) {
        this.fat = fat;
    }

    public void setSodium(int sodium) {
        this.sodium = sodium;
    }

    public void setCarbohydrate(int carbohydrate) {
        this.carbohydrate = carbohydrate;
    }


Wzorzec projektowy JavaBeans pozwala na tworzenie instancji obiektu nawet w przypadku dużej liczby parametrów, bez ryzyka ich pomieszania. Jednak utworzenie jednego obiektu wymaga wywołania wielu metod setter, a obiekty nie są spójne, dopóki nie zostaną w pełni utworzone. Z tego powodu klas nie można uczynić niezmiennymi.


Wzorzec projektowy budowniczego

Wzorzec projektowy budowniczego łączy w sobie zalety wzorca projektowego wzrastających konstruktorów i wzorca projektowego JavaBeans.

Klient zamiast tworzyć obiekt bezpośrednio, wywołuje konstruktor z wymaganymi parametrami, aby uzyskać obiekt typu budowniczego. Następnie ustawia wartości opcjonalnych parametrów za pomocą metod setter dostępnych w obiekcie typu budowniczego. Na koniec wywołuje metodę build() bez parametrów, aby uzyskać żądany obiekt.


public class NutritionFactsWithBuilderPattern {

    private final int servingSize;

    private final int servings;

    private final int calories;

    private final int fat;

    private final int sodium;

    private final int carbohydrate;

    private NutritionFactsWithBuilderPattern(Builder builder) {
        servingSize = builder.servingSize;
        servings = builder.servings;
        calories = builder.calories;
        fat = builder.fat;
        sodium = builder.sodium;
        carbohydrate = builder.carbohydrate;
    }

    public static class Builder {

        private final int servingSize;

        private final int servings;

        private int calories;

        private int fat;

        private int sodium;

        private int carbohydrate;

        public Builder(int servingSize, int servings) {
            this.servingSize = servingSize;
            this.servings = servings;
        }

        public Builder calories(int val) {
            calories = val;
            return this;
        }

        public Builder fat(int val) {
            fat = val;
            return this;
        }

        public Builder sodium(int val) {
            sodium = val;
            return this;
        }

        public Builder carbohydrate(int val) {
            calories = val;
            return this;
        }

        public NutritionFactsWithBuilderPattern build() {
            return new NutritionFactsWithBuilderPattern(this);
        }
    }


Konstruktor klasy Builder przyjmuje tylko wymagane parametry, a pozostałe opcjonalne parametry są ustawiane za pomocą metod setter. Na koniec metoda build() tworzy pełny obiekt NutritionFactsWithBuilderPattern. Klasa NutritionFactsWithBuilderPattern jest niezmienna, a metody setter klasy Builder zwracają samą siebie, co pozwala na wywoływanie ich w łańcuchu. Ten sposób nazywa się płynnym API lub łańcuchem metod.


NutritionFactsWithBuilderPattern nutritionFacts =
    new NutritionFactsWithBuilderPattern.Builder(240, 8)
        .calories(100)
        .sodium(35)


Z punktu widzenia klienta wzorzec projektowy budowniczego pozwala na łatwe i czytelne pisanie kodu.


Wzorzec projektowy budowniczego dobrze komponuje się z klasami hierarchicznymi

public abstract class Pizza {

    public enum Topping {
        HAM, MUSHROOM, ONION, PEPPER, SAUSAGE
    }

    final Set toppings;

    Pizza(Builder builder) {
        toppings = builder.toppings.clone();
    }

    abstract static class Builder> {

        private EnumSet toppings = EnumSet.noneOf(Topping.class);

        public T addTopping(Topping topping) {
            toppings.add(topping);
            return self();
        }

        abstract Pizza build();

        protected abstract T self();
    }


Klasa Pizza.Builder jest klasą generyczną z wykorzystaniem rekurencyjnego ograniczenia typu, a abstrakcyjna metoda self() pozwala na obsługę łańcucha metod bez rzutowania w klasach podrzędnych. W klasach podrzędnych należy ustawić wartość zwracaną tej abstrakcyjnej metody na samą siebie.

Spójrzmy teraz na podklasy Pizza: Pizza nowojorska i Calzone, aby zobaczyć elastyczność wzorca projektowego budowniczego.


public class NyPizza extends Pizza {

    public enum Size {
        SMALL, MEDIUM, LARGE
    }

    private final Size size; // wymagany parametr

    private NyPizza(Builder builder) {
        super(builder);
        size = builder.size;
    }

    public static class Builder extends Pizza.Builder {

        private final Size size;

        public Builder(Size size) {
            this.size = size;
        }

        @Override
        NyPizza build() {
            return new NyPizza(this);
        }

        @Override
        protected Builder self() {
            return this;
        }
    }

}

public class CalzonePizza extends Pizza {

    private final boolean sauceInside; // opcjonalny parametr

    private CalzonePizza(Builder builder) {
        super(builder);
        sauceInside = builder.sauceInside;
    }

    public static class Builder extends Pizza.Builder {

        private boolean sauceInside = false;

        public Builder sauceInside() {
            sauceInside = true;
            return this;
        }

        @Override
        CalzonePizza build() {
            return new CalzonePizza(this);
        }

        @Override
        protected Builder self() {
            return this;
        }
    }


Metoda build() zdefiniowana w konstruktorze każdej podklasy zwraca konkretną podklasę. Ta funkcja, w której metoda podklasy zwraca typ podklasy, a nie typ nadrzędny, jest nazywana kowariantnym typowanym zwracaniem. Dzięki temu klienci nie muszą rzutować.


NyPizza nyPizza = new NyPizza.Builder(Size.SMALL)
    .addTopping(Topping.SAUSAGE)
    .addTopping(Topping.ONION)
    .build();

CalzonePizza calzonePizza = new CalzonePizza.Builder()
    .addTopping(Topping.HAM)
    .sauceInside()


Klienci mogą łączyć ze sobą wyliczenia Pizza i wyliczenia każdej podklasy, a następnie używać odpowiednich metod, aby stworzyć pełny obiekt.


Wady wzorca projektowego budowniczego

  • Konieczność utworzenia obiektu typu budowniczego.
  • Kod może być rozwlekły.


Podsumowanie

Jeśli konstruktor lub statyczna metoda fabryczna musi obsługiwać dużą liczbę parametrów, rozważ użycie wzorca projektowego budowniczego.


Źródła

  • Effective Java
제이온
제이온
제이온
제이온
[Efektywny Java] Element 4. Aby zapobiec tworzeniu instancji, użyj prywatnego konstruktora Klasy pomocnicze, które zawierają tylko metody statyczne i pola, powinny mieć ustawiony modyfikator dostępu konstruktora na prywatny, aby zapobiec tworzeniu instancji. Dzięki temu można zapobiec błędnemu postrzeganiu konstruktora jako automatycznie genero

28 kwietnia 2024

[Efektywny Java] Element 5. Użyj wstrzykiwania zależności zamiast jawnego zarządzania zasobami Jeśli klasa zależy od zewnętrznych zasobów, lepiej nie używać singletonów ani statycznych klas narzędzi. Wstrzykiwanie zależności może poprawić elastyczność, ponowne użycie i łatwość testowania klasy, a wzorzec fabryki metod może prowadzić do bardziej wyd

28 kwietnia 2024

[Efektywny Java] Punkt 6. Unikaj niepotrzebnego tworzenia obiektów Przewodnik po sposobach zmniejszenia liczby niepotrzebnych tworzeń obiektów w Javie. W przypadku obiektów niezmiennych, takich jak String, Boolean, lepiej jest używać literałów, a wyrażenia regularne najlepiej buforować w instancji Pattern. Ponadto automa

28 kwietnia 2024

[Bez stopnia, przetrwanie jako programista] 13. Wywiad techniczny dla początkujących programistów Prezentujemy 7 często zadawanych pytań podczas wywiadu technicznego dla początkujących programistów oraz wskazówki, jak się do niego przygotować. Dowiedz się o pytaniach i strategiach odpowiedzi dotyczących takich dziedzin jak OOP, bazy danych, sieci, alg
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

1 kwietnia 2024

[Javascript] Struktura obiektu (V8) Obiekt JavaScript w silniku V8 jest optymalizowany jak struktura w zależności od stanu, przełączając się między szybkim trybem i trybem słownika, który działa jako mapa skrótów. Szybki tryb jest szybki, gdy klucz i wartość są prawie stałe, ale może spowol
곽경직
곽경직
곽경직
곽경직
곽경직

18 marca 2024

Pomysły na budowę domu w Minecrafcie Dowiedz się, jak zbudować niesamowity dom w Minecrafcie. Przedstawiamy różnorodne wskazówki, od prostych projektów po kreatywne aranżacje i trendy pomysły. Stwórz swój własny, wyjątkowy dom i baw się jeszcze lepiej w grze.
hunters
hunters
hunters
hunters
hunters

28 marca 2024

Jak Rust zapobiega błędom współbieżności Rust to potężny język, który rozwiązuje wyzwania związane z programowaniem współbieżnym. Jego system typów i model własności zapewniają bezpieczeństwo podczas przekazywania i udostępniania danych między wątkami. Wzory zmienności wewnętrznej, takie jak Mut
곽경직
곽경직
곽경직
곽경직
곽경직

28 marca 2024

[Nie mając wykształcenia, przetrwaj jako programista] 16. Wskazówki dotyczące tworzenia portfolio dla początkującego programisty Początkujący programiści (szczególnie ci bez wykształcenia) podczas tworzenia portfolio powinni jasno opisywać nie tylko technologie, ale także usługi lub funkcje, które opracowali. Na przykład w przypadku projektu „Społeczność dla osób poszukujących prac
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 kwietnia 2024

[Historia programisty SI] 09. Początek właściwego rozwoju po przydzieleniu do projektu SI Programista SI po przydzieleniu do projektu rozwija funkcje określone w RFP, ale częste zmiany wymagań klienta czynią szybkie opracowanie ważniejszym od wydajności ze względu na częste zmiany kodu. Dlatego w fazie rozwoju należy skupić się na wdrażaniu fu
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

18 kwietnia 2024