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

Esta é uma postagem traduzida por IA.

제이온

[Effective Java] Item 2: Considere um construtor se você tiver muitos parâmetros

  • Idioma de escrita: Coreana
  • País de referência: Todos os países country-flag

Selecionar idioma

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

Texto resumido pela IA durumis

  • Apresenta vários padrões para gerenciar efetivamente construtores com muitos parâmetros e analisa os prós e contras dos padrões de construtor hierárquico, beans Java e construtor.
  • O padrão de construtor oferece benefícios de legibilidade e estabilidade de código e é particularmente eficaz ao trabalhar com classes projetadas hierarquicamente.
  • O padrão de construtor permite que você escreva código mais claro, mas tem desvantagens, como a criação de objetos de construtor e código verboso.

Padrão de construtor incremental

Fábricas estáticas e construtores têm dificuldades em lidar com um número excessivo de parâmetros. Por exemplo, se uma classe tem 6 campos e queremos criar construtores para 2, 3, ... parâmetros, podemos usar o padrão de construtor incremental, como mostrado abaixo.


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);
    }


No entanto, mesmo assim, se o número de parâmetros aumentar, fica difícil entender o significado de cada valor ao ler o código e podemos confundir parâmetros com o mesmo tipo e inserir os valores incorretamente.


Padrão JavaBeans

O padrão JavaBeans cria um objeto com um construtor sem parâmetros e, em seguida, define os valores dos parâmetros desejados chamando os métodos setter.


public class NutritionFactsWithJavaBeansPattern {

    private int servingSize = -1; // Necessário. Sem valor padrão.

    private int servings = -1; // Necessário. Sem valor padrão.

    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;
    }


O padrão JavaBeans pode criar uma instância sem confundir os valores, mesmo se o número de parâmetros aumentar. No entanto, para criar um objeto, precisamos chamar vários métodos setter e a coerência é quebrada até que o objeto esteja totalmente completo. Por essa razão, a classe não pode ser imutável.


Padrão de construtor

O padrão de construtor geralmente é usado porque combina a estabilidade do padrão de construtor incremental com a legibilidade do padrão JavaBeans.

Em vez de criar o objeto diretamente, o cliente chama o construtor com apenas os parâmetros necessários para obter um objeto de construtor. Então, o objeto de construtor fornece uma espécie de método setter para definir os parâmetros opcionais desejados. Finalmente, chama o método build() sem parâmetros para obter o objeto desejado.


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);
        }
    }


O construtor dentro da classe Builder recebe apenas os parâmetros necessários e os parâmetros opcionais restantes são preenchidos por meio de uma espécie de método setter. E finalmente, o método build() é usado para criar o objeto NutritionFactsWithBuilderPattern completo. A classe NutritionFactsWithBuilderPattern é imutável e os métodos setter do construtor retornam o próprio construtor, permitindo que sejam chamados em cadeia. Esse método é chamado de API fluente ou encadeamento de métodos.


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


Do ponto de vista do cliente, o padrão de construtor torna o código mais fácil de escrever e ler.


O padrão de construtor combina bem com classes hierárquicas

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();
    }


A classe Pizza.Builder é um tipo genérico que usa restrições de tipo recursivo e, com o método abstrato self(), permite encadeamento de métodos sem conversão de tipo nas subclasses. As subclasses podem atribuir o valor de retorno desse método abstrato a si mesmas.

Agora, vamos ver as subclasses de Pizza, a pizza de Nova York e a Calzone, para ver a flexibilidade do padrão de construtor.


public class NyPizza extends Pizza {

    public enum Size {
        SMALL, MEDIUM, LARGE
    }

    private final Size size; // Parâmetro necessário

    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; // Parâmetro opcional

    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;
        }
    }


A classe build() definida no construtor de cada subclasse retorna a subclasse específica. A capacidade de um método de subclasse retornar um tipo diferente do tipo retornado por um método de superclasse é chamada de tipificação de retorno covariante. Com essa funcionalidade, o cliente não precisa fazer conversão de tipo.


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

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


Do ponto de vista do cliente, a enumeração Pizza e a enumeração de cada subclasse podem ser usadas em conjunto e o objeto pode ser concluído com os métodos apropriados.


Desvantagens do padrão de construtor

  • Você precisa criar um objeto de construtor.
  • O código é prolixo.


Resumindo

Considere o padrão de construtor se o construtor ou o método de fábrica estático precisar lidar com muitos parâmetros.


Fontes

  • Eficaz Java
제이온
제이온
제이온
제이온
[Effective Java] Item 1: Considere métodos de fábrica estáticos em vez de construtores Os métodos de fábrica estáticos são uma maneira flexível e eficiente de criar instâncias em vez de construtores. Eles podem ter um nome, retornar instâncias que atendem a condições específicas e melhorar o desempenho por meio do cache. Ao contrário do pad

27 de abril de 2024

[Effective Java] Item 4. Use a private constructor to prevent instantiation As for utility classes that contain only static methods and fields, it is good practice to set the access modifier of the constructor to private to prevent instantiation. This prevents users from mistaking the constructor for a automatically generated one

28 de abril de 2024

[Effective Java] Item 6. Evite a criação de objetos desnecessários Este é um guia sobre como reduzir a criação de objetos desnecessários em Java. Para objetos imutáveis como String, Boolean, é melhor usar literais e, para expressões regulares, é melhor armazenar em cache a instância Pattern. Além disso, o autoboxing pode

28 de abril de 2024

[Não graduado, sobrevivendo como desenvolvedor] 14. Resumo do conteúdo da entrevista técnica frequente para desenvolvedores juniores Guia de preparação para entrevista técnica para desenvolvedores juniores. Área de memória principal, estrutura de dados, RDBMS e NoSQL, orientação de procedimentos e orientação de objetos, sobreposição e sobrecarga, algoritmo de substituição de página, pr
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 de abril de 2024

[Sem graduação, sobrevivendo como desenvolvedor] 13. Entrevista técnica para desenvolvedores juniores Este artigo apresenta 7 perguntas frequentes em entrevistas técnicas para desenvolvedores juniores e dicas para se preparar para a entrevista. Explore perguntas e estratégias de resposta sobre vários campos, como OOP, banco de dados, rede, algoritmos, etc
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

1 de abril de 2024

[História do Desenvolvedor SI] 09. Início do Desenvolvimento Real após a Alocação do Projeto SI O desenvolvedor SI desenvolve as funções especificadas no RFP após a alocação do projeto, mas as frequentes mudanças de requisitos do cliente tornam a velocidade do desenvolvimento mais importante do que a eficiência, devido às frequentes alterações de có
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

18 de abril de 2024

[Javascript] Estrutura do Objeto (V8) O Objeto JavaScript no motor V8 é otimizado como uma estrutura dependendo do estado, alternando entre o modo Rápido e o modo Dicionário, que funciona como um mapa hash. O modo Rápido é rápido quando as chaves e valores são quase fixos, mas quando uma nova
곽경직
곽경직
곽경직
곽경직
곽경직

18 de março de 2024

Ideias de construção de casas no Minecraft Descubra como construir casas incríveis no Minecraft. Apresentamos dicas variadas, desde designs simples até interiores criativos e ideias modernas. Crie sua própria casa única e divirta-se ainda mais no jogo.
hunters
hunters
hunters
hunters
hunters

28 de março de 2024

Ideias para melhorar o programa de negociação automatizada Este artigo apresenta ideias para melhorar as funcionalidades do programa de negociação automatizada de Grid Trading, sugerindo a inclusão de gerenciamento de grandes eventos, lógica de gerenciamento de investimentos, funcionalidade de posição curta, entr
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마

21 de abril de 2024