Partage
  • Partager sur Facebook
  • Partager sur Twitter

Design Pattern : Décorator

La machine à Café

Sujet résolu
    1 août 2023 à 0:23:09

    Bonjour : Je m'exerce sur les designs pattern : j'ai essayé d'écrire du code sur une machine à café qui pourrait permettre de rajouter dans le café du sucre, du lait ou de la chantilly. (Je sais c'est très light !)

    Et de calculer le prix total de ce dernier suivant les ingrédients choisi.

    Voici ce que je pense être le diagramme de classe :

    Voici la sortie du programme :

    Je suis un café
    Je rajoute de la chantilly dans (Je rajoute du lait dans (Je rajoute du sucre dans (Je suis un café)))
    Le prix total de mon café est de : 8€ 

    J'aurais aimé avoir un retour sur le code écrit : est-il correct ?

    Merci d'avance :)

    #include <iostream>
    
    
    class Boisson {
     public:
      virtual ~Boisson() {}
      virtual std::string Description() const = 0;
      virtual double prix() = 0;
    };
    
    class Coffee : public Boisson {
    private:
    	double _price = 2; // 2€ le café.
     public:
      std::string Description() const override {
        return "Je suis un café";
      }
      double prix() {
    	  return _price;
      }
    };
    
    class DecoratorCoffee : public Boisson {
     protected:
    	Boisson* component_;
     public:
    	DecoratorCoffee(Boisson* component) : component_(component) {
      }
      std::string Description() const override {
        return this->component_->Description();
      }
      double prix() {
      	  return this->component_->prix();
        }
    };
    
    class Sucre : public DecoratorCoffee {
    private:
    	double _price = 1.0; // 1€ le sucre
     public:
    	Sucre(Boisson* component) : DecoratorCoffee(component) {
      }
      std::string Description() const override {
        return "Je rajoute du sucre dans (" + DecoratorCoffee::Description() + ")";
      }
      double prix() {
    	  return DecoratorCoffee::prix() + _price;
      }
    
    };
    
    class Lait : public DecoratorCoffee {
    private:
    	double _price = 3.0; // 3€ le lait
     public:
    	Lait(Boisson* component) : DecoratorCoffee(component) {
      }
    
      std::string Description() const override {
        return "Je rajoute du lait dans (" + DecoratorCoffee::Description() + ")";
      }
      double prix() {
    	  return DecoratorCoffee::prix() + _price;
      }
    
    };
    
    class Chantilly : public DecoratorCoffee {
    private:
    	double _price = 2.0; // 2€ la chantilly
     public:
    	Chantilly(Boisson* component) : DecoratorCoffee(component) {
      }
    
      std::string Description() const override {
        return "Je rajoute de la chantilly dans (" + DecoratorCoffee::Description() + ")";
      }
      double prix() {
    	  return DecoratorCoffee::prix() + _price;
      }
    
    };
    
    int main() {
    
      Boisson* Cafe = new Coffee;
      std::cout << Cafe->Description() << "\n";
    
      Boisson* CafeDecore = new Chantilly(new Lait(new Sucre(Cafe)));
      std::cout  << CafeDecore->Description() << "\n";
      std::cout  << "Le prix total de mon café est de : " << CafeDecore->prix() << "€ \n";
    
      delete Cafe;
      delete CafeDecore;
    
      return 0;
    }
    



    Kasimashi

    -
    Edité par Kasimashi 1 août 2023 à 0:34:09

    • Partager sur Facebook
    • Partager sur Twitter
      1 août 2023 à 14:01:58

      new Lait, new Sucre : comment sont-ils détruit quand tu n'en as plus besoin ?
      • Partager sur Facebook
      • Partager sur Twitter
      ...
        1 août 2023 à 15:29:55

        rouIoude a écrit:

        new Lait, new Sucre : comment sont-ils détruit quand tu n'en as plus besoin ?


        Merci beaucoup de ta remarque : j'ai corrigé en ce sens : est-ce mieux?

        Cependant je trouve au final le code client lourd ... Je me demande de plus comment pourrais-je faire pour enlever le sucre de mon expresso ;)

        Que se passe t-il si je met les instructions delete dans le mauvais ordre ?

        Voici le nouveau code :

        #include <iostream>
        
        
        class Boisson {
         public:
          virtual ~Boisson() {}
          virtual std::string Description() const = 0;
          virtual double prix() = 0;
        };
        
        class Coffee : public Boisson {
        private:
        	double _price = 2; // 2€ le café.
         public:
          std::string Description() const override {
            return "Un café";
          }
          double prix() {
        	  return _price;
          }
        };
        
        class Expresso : public Boisson {
        private:
        	double _price = 1.5; // 1.5€ l'expresso
         public:
          std::string Description() const override {
            return "Un expresso";
          }
          double prix() {
        	  return _price;
          }
        };
        
        class DecoratorBoisson : public Boisson {
         protected:
        	Boisson* component_;
         public:
        	DecoratorBoisson(Boisson* component) : component_(component) {
          }
        };
        
        class Sucre : public DecoratorBoisson {
        private:
        	double _price = 1.0; // 1€ le sucre
         public:
        	Sucre(Boisson* component) : DecoratorBoisson(component) {
          }
          std::string Description() const override {
            return "Je rajoute du sucre dans (" + component_->Description() + ")";
          }
          double prix() {
        	  return component_->prix() + _price;
          }
        
        };
        
        class Lait : public DecoratorBoisson {
        private:
        	double _price = 3.0; // 3€ le lait
         public:
        	Lait(Boisson* component) : DecoratorBoisson(component) {
          }
        
          std::string Description() const override {
            return "Je rajoute du lait dans (" + component_->Description() + ")";
          }
          double prix() {
        	  return component_->prix() + _price;
          }
        
        };
        
        class Chantilly : public DecoratorBoisson {
        private:
        	double _price = 2.0; // 2€ la chantilly
         public:
        	Chantilly(Boisson* component) : DecoratorBoisson(component) {
          }
        
          std::string Description() const override {
            return "Je rajoute de la chantilly dans (" + component_->Description() + ")";
          }
          double prix() {
        	  return component_->prix() + _price;
          }
        
        };
        
        int main() {
        
        	Boisson* Cafe = new Coffee;
        	std::cout << Cafe->Description() << "\n";
        
        
        	DecoratorBoisson *sucre1 = new Sucre(Cafe);
        	DecoratorBoisson *lait1 = new Lait(sucre1);
        	DecoratorBoisson *chantilly1 = new Chantilly(lait1);
        
        	Boisson* CafeDecore = chantilly1;
        
        	std::cout  << CafeDecore->Description() << "\n";
        	std::cout  << "Le prix total de mon café est de : " << CafeDecore->prix() << "€ \n";
        
        	delete Cafe;
        	delete chantilly1;
        	delete lait1;
        	delete sucre1;
        
        
        	Boisson* expresso = new Expresso();
        
        	DecoratorBoisson *sucre2 = new Sucre(expresso);
        	DecoratorBoisson *lait2 = new Lait(sucre2);
        	DecoratorBoisson *chantilly2 = new Chantilly(lait2);
        
        	Boisson* expressoDecore = chantilly2;
        
        	std::cout  << "Le prix total de mon expresso est de : " << expressoDecore->prix() << "€ \n";
        
        	delete expresso;
        	delete chantilly2;
        	delete lait2;
        	delete sucre2;
        
          return 0;
        }
        



        -
        Edité par Kasimashi 1 août 2023 à 15:30:58

        • Partager sur Facebook
        • Partager sur Twitter
          1 août 2023 à 17:41:39

          Et pourquoi avoir utiliser des pointeurs et new ? (Tu as vu qu'il était vite fait d'oublier de libéré la mémoire allouée). Tu peux créer des objets sur la pile et les passer par référence.

          PS : tu devrais mettre les fonctions membres redéfinies prix override.

          • Partager sur Facebook
          • Partager sur Twitter
          ...
            1 août 2023 à 21:24:09

            rouIoude a écrit:

            Et pourquoi avoir utiliser des pointeurs et new ? (Tu as vu qu'il était vite fait d'oublier de libéré la mémoire allouée). Tu peux créer des objets sur la pile et les passer par référence.

            PS : tu devrais mettre les fonctions membres redéfinies prix override.


            Merci pour ta réponse.

            Peux tu être plus précis ? 

            Cela donne quoi dans le code je ne vois pas trop ce que tu souhaites faire ?

            Merci !

            Kaismashi

            • Partager sur Facebook
            • Partager sur Twitter
              1 août 2023 à 21:29:31

              Bonjour,

              Dans l' include de la bibliothèque standard <memory> , tu as la classe "exception safe" std::unique_ptr<T> qui va gérer pour toi la durée de vie de l'objet pointé.

              • Partager sur Facebook
              • Partager sur Twitter

              Mon site web de jeux SDL2 entre autres : https://www.ant01.fr

                1 août 2023 à 21:38:57

                Warren79 a écrit:

                Bonjour,

                Dans l' include de la bibliothèque standard <memory> , tu as la classe "exception safe" std::unique_ptr<T> qui va gérer pour toi la durée de vie de l'objet pointé.


                Merci encore pour la réponse mais c'est du chinois pour moi : désolé ^^
                • Partager sur Facebook
                • Partager sur Twitter
                  1 août 2023 à 22:21:20

                  Ils t'expliquent juste d'utiliser des pointeurs intelligents, par exemple

                  Boisson* component
                  // devient
                  std::unique_ptr<Boisson> component

                  Et tu peux remplacer les new par des make_unique.

                  Tu peux également améliorer les constexpr, les const, les =default.

                  A part cela, ton implémentation du DP decorator est comprise et correcte.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    1 août 2023 à 23:24:49

                    Kasimashi a écrit:

                    Cela donne quoi dans le code je ne vois pas trop ce que tu souhaites faire ?

                    Je pensais à un truc comme ça. C'est des Pizzas à la place du café (Je ne suis pas connaisseur en café).

                    #include <iostream>
                    #include <string>
                    
                    enum eTaille {moyenne=20, standard=26, grande=30};
                    
                    struct Pizza
                    {
                        virtual std::string str() const = 0;
                    };
                    
                    class Taille : public Pizza
                    {
                        eTaille m_taille;
                    
                    public:
                        Taille(eTaille taille): m_taille{taille} {}
                        std::string str() const override
                        {
                            if(m_taille==moyenne) return std::string("Pizza moyenne ");
                            if(m_taille==grande) return std::string("Pizza grande ");
                            return std::string("Pizza standard ");
                        }
                    };
                    
                    class DecoPizza : public Pizza
                    {
                     protected:
                        Pizza& m_pizza;
                     public:
                        DecoPizza(Pizza& pizza) : m_pizza(pizza) {
                      }
                    };
                    
                    class Sauce : public DecoPizza
                    {
                        std::string m_sauce;
                    public:
                        Sauce(std::string c, Pizza&& pizza): DecoPizza(pizza), m_sauce(c) {}
                        std::string str() const override
                        {
                            return m_pizza.str() + std::string(" avec sauce ") + m_sauce;
                        }
                    };
                    
                    class Garniture : public DecoPizza
                    {
                        std::string m_garniture;
                    public:
                        Garniture(std::string c, Pizza&& pizza):  DecoPizza(pizza), m_garniture(c) {}
                        std::string str() const override
                        {
                            return m_pizza.str() + std::string(" avec garniture ") + m_garniture;
                        }
                    };
                    
                    int main()
                    {
                        Pizza&& ma_Pizza {Sauce("moutarde",(Garniture("jambon",Garniture("fromage",Taille(grande)))))};
                        std::cout << ma_Pizza.str() << '\n';
                    }

                    -
                    Edité par rouIoude 2 août 2023 à 18:39:30

                    • Partager sur Facebook
                    • Partager sur Twitter
                    ...
                      2 août 2023 à 22:20:18

                      Merci de vos réponse je vais étudier tout cela tranquillement ! :)

                      Bonne continuation !

                      Kasimashi.

                      • Partager sur Facebook
                      • Partager sur Twitter
                        2 août 2023 à 22:30:19

                        rouIoude a écrit:

                        Kasimashi a écrit:

                        Cela donne quoi dans le code je ne vois pas trop ce que tu souhaites faire ?

                        Je pensais à un truc comme ça. C'est des Pizzas à la place du café (Je ne suis pas connaisseur en café).

                        #include <iostream>
                        #include <string>
                        
                        enum eTaille {moyenne=20, standard=26, grande=30};
                        
                        struct Pizza
                        {
                            virtual std::string str() const = 0;
                        };
                        
                        class Taille : public Pizza
                        {
                            eTaille m_taille;
                        
                        public:
                            Taille(eTaille taille): m_taille{taille} {}
                            std::string str() const override
                            {
                                if(m_taille==moyenne) return std::string("Pizza moyenne ");
                                if(m_taille==grande) return std::string("Pizza grande ");
                                return std::string("Pizza standard ");
                            }
                        };
                        
                        class DecoPizza : public Pizza
                        {
                         protected:
                            Pizza& m_pizza;
                         public:
                            DecoPizza(Pizza& pizza) : m_pizza(pizza) {
                          }
                        };
                        
                        class Sauce : public DecoPizza
                        {
                            std::string m_sauce;
                        public:
                            Sauce(std::string c, Pizza&& pizza): DecoPizza(pizza), m_sauce(c) {}
                            std::string str() const override
                            {
                                return m_pizza.str() + std::string(" avec sauce ") + m_sauce;
                            }
                        };
                        
                        class Garniture : public DecoPizza
                        {
                            std::string m_garniture;
                        public:
                            Garniture(std::string c, Pizza&& pizza):  DecoPizza(pizza), m_garniture(c) {}
                            std::string str() const override
                            {
                                return m_pizza.str() + std::string(" avec garniture ") + m_garniture;
                            }
                        };
                        
                        int main()
                        {
                            Pizza&& ma_Pizza {Sauce("moutarde",(Garniture("jambon",Garniture("fromage",Taille(grande)))))};
                            std::cout << ma_Pizza.str() << '\n';
                        }

                        -
                        Edité par rouIoude il y a environ 3 heures

                        Ce n'est pas correct en termes de durée de vie des objets.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          3 août 2023 à 10:46:07

                          gbdivers a écrit:

                          Ce n'est pas correct en termes de durée de vie des objets.

                          Effectivement, il ne reste que la sauce moutarde.

                          C'est peut-être mieux comme ça :

                          #include <iostream>
                          #include <string>
                          
                          enum eTaille {moyenne=20, standard=26, grande=30};
                          
                          struct Pizza
                          {
                              virtual std::string str() const = 0;
                              virtual ~Pizza(){};
                          };
                          
                          class Taille : public Pizza
                          {
                              eTaille m_taille;
                          public:
                              Taille(eTaille taille): m_taille(taille) {}
                              std::string str() const override
                              {
                                  if(m_taille==moyenne) return std::string("Pizza moyenne ");
                                  if(m_taille==grande) return std::string("Pizza grande ");
                                  return std::string("Pizza standard ");
                              }
                          };
                          
                          class DecoPizza : public Pizza
                          {
                           protected:
                              Pizza& m_pizza;
                           public:
                              DecoPizza(Pizza& pizza) : m_pizza(pizza) {}
                          };
                          
                          class Sauce : public DecoPizza
                          {
                              std::string m_sauce;
                          public:
                              Sauce(std::string c, Pizza& pizza): DecoPizza(pizza), m_sauce(c) {}
                              std::string str() const override
                              {
                                  return m_pizza.str() + std::string(" avec sauce ") + m_sauce;
                              }
                          };
                          
                          class Garniture : public DecoPizza
                          {
                              std::string m_garniture;
                          public:
                              Garniture(std::string c, Pizza& pizza):  DecoPizza(pizza), m_garniture(c) {}
                              std::string str() const override
                              {
                                  return m_pizza.str() + std::string(" avec garniture ") + m_garniture;
                              }
                          };
                          
                          int main()
                          {
                              auto pizza_grande {Taille(grande)};
                              auto fromage {Garniture("fromage", pizza_grande)};
                              auto jambon {Garniture("jambon", fromage)};
                              auto ma_Pizza {Sauce("moutarde", jambon)};
                          
                              std::cout << ma_Pizza.str() << '\n';
                          }

                          -
                          Edité par rouIoude 3 août 2023 à 11:02:54

                          • Partager sur Facebook
                          • Partager sur Twitter
                          ...

                          Design Pattern : Décorator

                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                          • Editeur
                          • Markdown