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

Ceci est un post traduit par IA.

제이온

[Effective Java] Item 2. Si vous avez beaucoup de paramètres dans le constructeur, envisagez d'utiliser un générateur

Choisir la langue

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

Texte résumé par l'IA durumis

  • Il présente divers modèles pour gérer efficacement les constructeurs avec un grand nombre de paramètres, et compare les avantages et les inconvénients des modèles de constructeurs graduels, des modèles de beans Java et des modèles de générateurs.
  • Le modèle de générateur présente l'avantage d'améliorer la lisibilité et la stabilité du code, et il est encore plus efficace lorsqu'il est utilisé avec des classes conçues de manière hiérarchique.
  • Le modèle de générateur permet d'écrire du code plus clair, mais présente l'inconvénient de créer des objets générateurs et d'alourdir le code.

Modèle de constructeur incrémental

Les usines statiques et les constructeurs ont tous deux du mal à faire face correctement à un grand nombre de paramètres. Par exemple, si la classe a 6 champs et que vous souhaitez diviser le constructeur en cas de 2 paramètres, 3 paramètres, ..., vous pouvez utiliser le modèle de constructeur incrémental comme indiqué ci-dessous.


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


Mais même cela, si le nombre de paramètres augmente, le code devient difficile à lire car la signification de chaque valeur est confuse et les paramètres du même type peuvent être confondus lors de l'entrée de valeurs.


Modèle de Beans Java

Le modèle de Beans Java crée un objet avec un constructeur sans paramètre, puis appelle des méthodes setter pour définir les valeurs des paramètres souhaités.


public class NutritionFactsWithJavaBeansPattern {

    private int servingSize = -1; // Obligatoire. Pas de valeur par défaut.

    private int servings = -1; // Obligatoire. Pas de valeur par défaut.

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


Le modèle de Beans Java peut créer des instances sans confusion de valeurs, même si le nombre de paramètres augmente. Cependant, la création d'un objet nécessite plusieurs appels de méthodes setter et la cohérence est rompue jusqu'à ce que l'objet soit complètement terminé. Pour cette raison, la classe ne peut pas être rendue immuable.


Modèle de constructeur

Le modèle de constructeur, qui combine la sécurité du modèle de constructeur incrémental et la lisibilité du modèle de Beans Java, est généralement utilisé.

Au lieu de créer directement l'objet souhaité, le client appelle le constructeur avec les paramètres obligatoires pour obtenir un objet constructeur. Ensuite, l'objet constructeur fournit une sorte de méthodes setter pour définir les paramètres optionnels souhaités. Enfin, il appelle la méthode build() sans paramètre pour obtenir l'objet souhaité.


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


Le constructeur de la classe Builder accepte uniquement les paramètres obligatoires et les autres paramètres optionnels sont remplis par une sorte de méthodes setter. Enfin, la méthode build() crée l'objet NutritionFactsWithBuilderPattern complet. NutritionFactsWithBuilderPattern est immuable et les méthodes setter du constructeur renvoient le constructeur lui-même, ce qui permet des appels en chaîne. Cette approche est appelée API fluide ou chaînage de méthodes.


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


Du point de vue du client, le modèle de constructeur permet d'écrire et de lire facilement le code.


Modèle de constructeur bien adapté aux classes hiérarchiques

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 classe Pizza.Builder est un type générique utilisant une limitation de type récursive et la méthode abstraite self() est ajoutée pour permettre le chaînage de méthodes sans conversion de type dans les sous-classes. Dans les sous-classes, la valeur de retour de cette méthode abstraite doit être elle-même.

Examinons maintenant la pizza new-yorkaise et la calzone, qui sont des sous-classes de Pizza, pour découvrir la flexibilité du modèle de constructeur.


public class NyPizza extends Pizza {

    public enum Size {
        SMALL, MEDIUM, LARGE
    }

    private final Size size; // Paramètre obligatoire

    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; // Paramètre optionnel

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


La classe build() définie par le constructeur de chaque sous-classe renvoie la sous-classe concrète. Le fait qu'une méthode de la sous-classe renvoie un type inférieur à celui renvoyé par la méthode de la super-classe est appelé typage de retour covariant. Grâce à cette fonctionnalité, le client n'a pas besoin de convertir le type.


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

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


Du point de vue du client, il est possible de mélanger l'énumération de Pizza et l'énumération de chaque sous-classe et de compléter l'objet avec les méthodes appropriées.


Inconvénients du modèle de constructeur

  • Il faut créer un objet constructeur.
  • Le code est prolixe.


Résumé

Si le constructeur ou la méthode d'usine statique doit gérer un grand nombre de paramètres, envisagez le modèle de constructeur.


Sources

  • Effective Java
제이온
제이온
제이온
제이온
[Efficace Java] Item 1. Envisager des méthodes d'usine statiques à la place des constructeurs Les méthodes d'usine statiques sont un moyen flexible et efficace de créer des instances à la place des constructeurs. Elles peuvent avoir un nom, renvoyer des instances répondant à des conditions spécifiques et améliorer les performances grâce à la mise

27 avril 2024

[Effective Java] Item 4 : Utilisez un constructeur privé pour empêcher l'instanciation Pour les classes utilitaires qui ne contiennent que des méthodes et des champs statiques, il est préférable de définir l'accès du constructeur sur privé pour empêcher l'instanciation. Cela permet d'éviter que les utilisateurs ne confondent le constructeur

28 avril 2024

[Effective Java] Item 5. Utilisez l'injection de dépendances au lieu de spécifier les ressources Si une classe dépend de ressources externes, il est préférable d'éviter d'utiliser les singletons et les classes utilitaires statiques. L'injection de dépendances peut améliorer la flexibilité, la réutilisabilité et la testabilité de la classe, et l'utili

28 avril 2024

[Non-majors, Surviving as Developers] 14. Résumé des questions d'entrevue technique fréquemment posées aux développeurs débutants Guide de préparation aux entrevues techniques pour les développeurs débutants. Zone de mémoire principale, structures de données, RDBMS et NoSQL, programmation procédurale et orientée objet, surcharge et surcharge, algorithmes de remplacement de page, pro
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 avril 2024

[Non-spécialiste, Survivre en tant que développeur] 9. Sites à créer pour un bon portfolio Voici trois types de sites que les étudiants de formations financées par l'État ou de bootcamps peuvent créer comme portfolio pour l'emploi. Vous pouvez développer un intranet, un ERP, un système de gestion des ressources humaines, etc. ou cloner des serv
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

30 mars 2024

[Histoire d'un développeur SI] 03. Préparation de l'entretien d'embauche dans une entreprise SI L'entretien d'embauche pour les développeurs SI met davantage l'accent sur la capacité de codage que sur les compétences techniques élevées. Ainsi, la compréhension de la structure Spring + mybatis apprise dans les écoles de formation subventionnées par l
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

16 avril 2024

L'importance d'un logiciel de calcul et d'estimation rentable pour réduire l'empreinte carbone dans les projets de construction L'adoption de logiciels de calcul et d'estimation est de plus en plus considérée comme une stratégie clé pour réduire les émissions de carbone dans l'industrie de la construction. Ces logiciels peuvent aider à fournir des estimations précises des matériau
durumis AI News Japan
durumis AI News Japan
durumis AI News Japan
durumis AI News Japan

27 mai 2024

Modélisation de données conceptuelle La modélisation de données conceptuelle est le processus de séparation des entités et de représentation de leurs relations sous forme de diagramme ERD. Une entité est une unité d'information indépendante et un attribut est une donnée possédée par une enti
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그

8 avril 2024

[Javascript] Structure d'objet (V8) L'objet JavaScript dans le moteur V8 est optimisé comme une structure en fonction de l'état, passant du mode Fast, optimisé comme une structure, au mode Dictionary qui fonctionne comme une table de hachage. Le mode Fast est rapide lorsque les clés et les
곽경직
곽경직
곽경직
곽경직
곽경직

18 mars 2024