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 es una publicación traducida por IA.

제이온

[Effective Java] Item 2. Considere un constructor si el constructor tiene muchos parámetros

Seleccionar idioma

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

Texto resumido por la IA durumis

  • Presenta varios patrones para administrar eficientemente los constructores con muchos parámetros y analiza las ventajas y desventajas de los patrones de constructor escalonado, Java Beans y constructor.
  • El patrón de constructor tiene la ventaja de mejorar la legibilidad y la estabilidad del código, y es particularmente eficaz cuando se utiliza con clases diseñadas jerárquicamente.
  • El patrón de constructor permite escribir código de manera más clara, pero tiene la desventaja de crear objetos de constructor y código prolijo.

Patrón de constructor incremental

Las fábricas estáticas y los constructores tienen dificultades para manejar adecuadamente una gran cantidad de parámetros. Por ejemplo, si una clase tiene 6 campos y queremos separar los constructores para 2, 3, ... parámetros, podemos usar el patrón de constructor incremental como se muestra a continuación.


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


Sin embargo, incluso con esto, si hay muchos parámetros, el código puede ser difícil de leer, ya que puede ser difícil recordar el significado de cada valor, y los parámetros del mismo tipo pueden confundirse y asignarse valores incorrectos.


Patrón de JavaBeans

El patrón de JavaBeans crea objetos con un constructor sin parámetros y luego utiliza los métodos setter para establecer los valores de los parámetros deseados.


public class NutritionFactsWithJavaBeansPattern {

    private int servingSize = -1; // Obligatorio. Sin valor predeterminado.

    private int servings = -1; // Obligatorio. Sin valor predeterminado.

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


El patrón de JavaBeans permite crear instancias sin confusión incluso con muchos parámetros. Sin embargo, se requieren varias llamadas a métodos setter para crear un objeto, y la coherencia se pierde hasta que el objeto está completamente construido. Por lo tanto, las clases no pueden hacerse inmutables.


Patrón de constructor

El patrón de constructor, que combina la estabilidad del patrón de constructor incremental y la legibilidad del patrón de JavaBeans, se utiliza principalmente.

En lugar de crear el objeto directamente, el cliente llama al constructor con solo los parámetros obligatorios para obtener un objeto constructor. Luego, utiliza los métodos setter proporcionados por el objeto constructor para establecer los parámetros opcionales deseados. Finalmente, llama al método build(), que no tiene parámetros, para obtener el objeto deseado.


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


El constructor dentro de la clase Builder solo toma los parámetros obligatorios, y los demás parámetros opcionales se rellenan mediante un tipo de método setter. Finalmente, el método build() crea el objeto NutritionFactsWithBuilderPattern completado. La clase NutritionFactsWithBuilderPattern es inmutable, y los métodos setter del constructor devuelven el constructor mismo, por lo que pueden ser llamados en cadena. Este enfoque se conoce como API fluida o encadenamiento de métodos.


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


Desde el punto de vista del cliente, el patrón de constructor permite escribir y leer el código de forma fácil y sencilla.


El patrón de constructor funciona bien con clases jerá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();
    }


La clase Pizza.Builder es un tipo genérico que utiliza la limitación de tipo recursivo, y el método abstracto self() añadido permite que las subclases admitan el encadenamiento de métodos sin necesidad de conversión de tipo. Las subclases solo tienen que devolver su propia instancia en este método abstracto.

Ahora, veamos las subclases de Pizza, New York Pizza y Calzone Pizza, para experimentar la flexibilidad del patrón de constructor.


public class NyPizza extends Pizza {

    public enum Size {
        SMALL, MEDIUM, LARGE
    }

    private final Size size; // Parámetro obligatorio

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


El método build() definido en el constructor de cada subclase devuelve la subclase específica. La capacidad de que los métodos de las subclases devuelvan un tipo que no sea el tipo devuelto por los métodos de la superclase, sino un tipo inferior, se denomina escritura de tipo de retorno covariante. Al utilizar esta característica, el cliente no necesita realizar conversiones 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()


Desde la perspectiva del cliente, se puede utilizar la enumeración de Pizza y la enumeración de cada subclase juntas, y el objeto se puede completar utilizando los métodos apropiados para cada uno.


Desventajas del patrón de constructor

  • Hay que crear un objeto constructor.
  • El código es verboso.


Resumen

Si el constructor o el método de fábrica estático tiene muchos parámetros para manejar, considera el patrón de constructor.


Fuente

  • Effective Java
제이온
제이온
제이온
제이온
[Effective Java] Item 4. Use a private constructor to prevent instantiation Las clases de utilidad que contienen solo métodos y campos estáticos deben configurar el modificador de acceso de su constructor como privado para evitar la creación de instancias. Esto evita que los usuarios asuman que el constructor es generado automáti

28 de abril de 2024

[Effective Java] Item 6. Evita la creación innecesaria de objetos Esta es una guía sobre cómo reducir la creación innecesaria de objetos en Java. Para objetos inmutables como String y Boolean, es mejor usar literales y para expresiones regulares, es mejor almacenar en caché las instancias de Pattern. Además, el autoboxi

28 de abril de 2024

[Effective Java] Item 5. Utilice la inyección de dependencia en lugar de especificar recursos Si una clase depende de recursos externos, es mejor no usar singletons ni clases de utilidad estáticas. La inyección de dependencia puede mejorar la flexibilidad, la reutilización y la facilidad de prueba de la clase, y el uso del patrón de método de fábr

28 de abril de 2024

Cómo Rust previene los errores de concurrencia Rust es un lenguaje poderoso que resuelve los desafíos de la programación concurrente. Su sistema de tipos y modelo de propiedad hacen que el intercambio y uso compartido de datos entre subprocesos sea seguro. Mediante patrones de mutabilidad interna como
곽경직
곽경직
곽경직
곽경직
곽경직

28 de marzo de 2024

[Javascript] Estructura de objetos (V8) El objeto JavaScript en el motor V8 se optimiza como una estructura, según el estado, en un modo rápido y se convierte en un modo de diccionario que funciona como un mapa hash. El modo rápido es rápido cuando la clave y el valor son casi fijos, pero cuand
곽경직
곽경직
곽경직
곽경직
곽경직

18 de marzo de 2024

[No técnico, sobrevivir como desarrollador] 9. Sitios web adecuados para crear un portafolio Se presentan tres tipos de sitios web que son adecuados para que los estudiantes de becas o bootcamps los creen como portafolios de empleo. Puedes desarrollar groupware, ERP, sistemas internos de recursos humanos, etc. que se utilizan comúnmente en las em
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

30 de marzo de 2024

¿Qué es el método de desarrollo en cascada? El método de desarrollo en cascada es una metodología tradicional que divide el proceso de desarrollo de software en etapas secuenciales: análisis de requisitos, diseño, implementación, prueba, implementación y mantenimiento. Este método tiene la ventaja
꿈많은청년들
꿈많은청년들
꿈많은청년들
꿈많은청년들
꿈많은청년들

14 de mayo de 2024

[python] Fundamentos de Python 1: Introducción a los Módulos de Python En este artículo, se describe la migración de un programa desarrollado en PHP a Python, incluyendo los conceptos básicos de Python y el uso de módulos. Python es un lenguaje de script que admite el tipeo dinámico y es independiente de la plataforma. Ofrec
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

27 de marzo de 2024

[Sin un título, convirtiéndose en desarrollador] 13. Entrevista técnica para desarrolladores junior Presentamos 7 preguntas frecuentes en las entrevistas técnicas para desarrolladores junior y consejos para prepararse para la entrevista. Explore las preguntas y estrategias de respuesta sobre una variedad de temas, como OOP, bases de datos, redes, algori
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

1 de abril de 2024