IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Evenements et design pattern Observer


Sujet :

C#

  1. #1
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2007
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2007
    Messages : 257
    Par défaut Evenements et design pattern Observer
    Bonsoir,

    J'apprends actuellement le C# et j'ai un problème de compréhension par rapport aux événements et leur utilisation avec le design pattern Observer.
    Si quelqu'un pourrait m'expliquer à quoi servent concrètement les événements ainsi que comment on les implémente,puis si c'est possible quel ajout est apporté par le design pattern Observer et comment l'implémente t-on.

    Merci d'avance

  2. #2
    Rédacteur
    Avatar de Paul Musso
    Profil pro
    Inscrit en
    Août 2008
    Messages
    368
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Août 2008
    Messages : 368
    Par défaut
    Bonjour,

    Les évènements sont utilisés pour définir des méthodes qui seront appelées ultérieurement. Ils permettent d'ajouter ou de supprimer simplement une méthode et de les appeler.

    Petit exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Program
    {
        public event Action<int> Evenement;
     
        public Program()
        {
            Evenement += i => Console.WriteLine(i);
            Evenement(3);
        }
     
        static void Main(string[] args)
        {
            new Program();
            Console.ReadKey();
        }
    }
    La déclaration d'un évènement se décompose ainsi :
    <Portée(public|private|protected)> event <TypeDeDélégué> <Nom de l'évènement>.

    Le type de délégué définit la signature des méthodes acceptées par l'évènement. Dans l'exemple, c'est le délégué Action<int> qui est définit, celui-ci prend en paramètre un entier et ne renvoie rien (void).

    Dans le constructeur de la classe Program, on assigne donc une méthode ayant la même signature, ici : i => Console.WriteLine(i);. Pour info, cela pourrait s'écrire aussi : delegate(int i) { Console.WriteLine(i); }.

    Finalement, pour appeler toutes les méthodes enregistrées dans l'évènement, il suffit de faire la chose suivante : Evenement(3);

    Cette phrase me plait : Les évenements sont aux délégués ce que sont les propriétés aux variables membres.

    Concernant le pattern Observer, les évènements sont une implémentation de ce pattern. Ils permettent d'abonner une classe à une autre en respectant le principe de faible couplage / forte cohérence. C'est à dire que la classe appelant les méthodes des classes abonnées ne connait pas pour autant ces classes.

    En .Net, les évènements sont beaucoup utilsées dans la partie IHM, que ce soit en ASP.Net, WPF, Winform et autre. Par exemple, le fait de cliquer sur un bouton est matérialisé par un évènement. Il suffit simplement d'ajouter une méthode à l'évènement pour que celle-ci soit appelée quand le bouton est pressé. C'est très intuitif.

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Pour faire simple, on peut dire que "s'abonner à un évènement" est l'équivalent C# de "s'inscrire comme observateur" dans le pattern Observer

  4. #4
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2007
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2007
    Messages : 257
    Par défaut
    Bonjour,
    Tout d'abord merci pour les réponses.
    Par rapport à ta réponse Paul,je ne comprends pas pourquoi on utiliserait pas les délégués directement:si je declare un délégué avec une signature spécifique,je peux trés bien lui ajouter plusieurs fonctions correspondant à cette signature et ainsi appeler le délégué qui appelera toutes les fonctions qui lui sont associéés,donc pourquoi utiliser un événement?

    Dans mon cas, je dois faire un programme qui gère un magasin qui propose plusieurs produits.Dès qu'un client passe une commande sur un produit particulier,la quantité commandée est diminuée au produit(si la quantité est disponible),puis si la quantité restante pour ce produit est inférieure à sa quantité minimum,l'objet(le produit) dois avertir un fournisseur(donc une autre classe) qu'il a besoin d'une certaine quantité afin de revenir au dessus de ce minimum.
    J'ai pensé qu'à la modification de la quantité du produit,il y ait vérification si elle descend en dessous de la quantité minimum,et si c'est le cas informer le fournisseur,mais je vois pas comment implémenter ca en utilisant le design pattern Observer.

    Merci

  5. #5
    Rédacteur
    Avatar de Paul Musso
    Profil pro
    Inscrit en
    Août 2008
    Messages
    368
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Août 2008
    Messages : 368
    Par défaut
    Alors,

    Un évènement fournit les méthodes ajouter et supprimer des délégués, grâce aux opérateurs += et -=. Voila pourquoi je fais le parallèle entre un événement/délégué et propriété/variable membre.

    Pour ton exemple, je mettrai un évènement dans la classe Produit. Ton autre classe qui doit commander des produits doit fournir une méthode pour s'abonner à cet évènement.

    Si la condition dans la classe produit est vérifiée, tu dois exécuter l'évènement, ce qui appelle toutes les méthodes abonnées à celui-ci. Au final, la méthode commandant les produits sera appellée.

  6. #6
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2007
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2007
    Messages : 257
    Par défaut
    Je suis d'accord sur le fait que l'événement sera placé dans la classe produit car c'est elle qui vérifie la condition et génére l'événement si elle est vraie.
    Mais pour ce qui est des classes observatrices,j'ai qu'ici en fait que la classe Fournisseur car c'est lui qui doit etre informé au cas ou l'événement est appelé,mais par rapport aux méthodes associées à l'événement,est ce qu'elles doivent avoir une signature particulière(recevant un object et EventArgs ou dérivé) ou pas?et quelle est logiquement l'action qui doit etre faite dans cette méthode?

    Merci

  7. #7
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2007
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2007
    Messages : 257
    Par défaut
    Bonsoir,
    Finalement j'ai eu les réponses à mes questions précédentes mais merci quand meme.
    A part ca j'aurais une autre question.
    Si j'ai deux classes construites de cette facon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    public delegate void RedLineEvent(object sender, EventArgs e);
     
    public class Product
    {
          //members
          protected uint _quantity;
          protected uint _quantMin;
          //properties
          public uint Quantity
            {
                get { return _quantity; }
                set 
                {
                    if (value >= 0)
                    {
                        _quantity = value;
                        if (value < _quantMin)
                        {
                            if (redLineReached != null)
                                //call redLineReached event,transmit the product itself 
                                //and EventArgs empty object
                                redLineReached(this, EventArgs.Empty);
                        }
                    }
                }
            }
            public uint QuantMin
            {
                get { return _quantMin; }
                set 
                {
                    if(value>=0)
                        _quantMin = value;
                }
            }
    }
     
    public class Store
    {
         private List<Product> warehouse;
         public event RedLineEvent redLineReached;
    }
    Je m'explique:j'ai une classe "Store" qui contient un liste "warehouse" de produit qui pour chacun sont définis une quantité disponible et une quantité minimum.
    Lorsqu'on modifie la quantité d'une des instances de la classe "Product" se trouvant dans la liste "warehouse",la propriété du membre privé "_quantity" est appelée,la fonction set modifie donc le membre "_quantity" puis vérifie ensuite si la quantité disponible est inférieure à la quantité minimum et si oui elle appele l'événement "redLineReached" de l'instance de la classe "Store".
    Le problème est que je n'ai pas accés depuis l'instance de la classe "Product" située dans la liste "warehouse",à l'event "redLineReached" de la classe "Store".
    Si quelqu'un a une solution à ca,ca m'aiderait beaucoup vu que ca me bloque.

    Merci

  8. #8
    Rédacteur/Modérateur
    Avatar de Skalp
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 694
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 694
    Par défaut
    Pourquoi mets-tu l'évènement RedLineEvent dans la classe Store ?
    Il me semble que c'est un évènement propre à un produit, il devrait donc être dans la classe Product.

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    d'ailleurs, comme ça ça ne peut pas fonctionner : un évènement ne peut être déclenché que dans la classe qui le déclare

  10. #10
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2007
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2007
    Messages : 257
    Par défaut
    C'est bien ce que j'avais compris,sinon la solution que j'ai trouvé c'est de placer un event dans la classe "Store" et un event dans la classe "Product".
    Lorsque la quantité disponible d'un objet s'avère inférieure à sa quantité minimum,l'event de cet objet(qui est de type "Product") est appelé d'où l'appel d'une fonction CallEvent placé dans la classe "Store" qui appellera ensuite l'événement qui m'intéresse situé dans la classe "Store".
    Est ce que cette solution serait correcte?
    Je vous joins le code,ce sera plus clair.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
     
    public delegate void RedLineEvent(object sender, EventArgs e);
     
    public class Product
    {
          //members
          protected uint _quantity;
          protected uint _quantMin;
          //event
          public event RedLineEvent redLineReached;
          //properties
          public uint Quantity
            {
                get { return _quantity; }
                set 
                {
                    if (value >= 0)
                    {
                        _quantity = value;
                        if (value < _quantMin)
                        {
                            if (redLineReached != null)
                                //call redLineReached event,transmit the product itself 
                                //and EventArgs empty object
                                redLineReached(this, EventArgs.Empty);
                                //cette fois ci j'appele l'événement de la classe Product
                        }
                    }
                }
            }
            public uint QuantMin
            {
                get { return _quantMin; }
                set 
                {
                    if(value>=0)
                        _quantMin = value;
                }
            }
    }
     
    public class Store
    {
         private List<Product> warehouse;
         //event
         public event RedLineEvent redLineReached;
     
         //constructeur
     
        public void AddStore(Product a)
        {
             if(!warehouse.Contains(a))
             {
                warehouse.Add(a);
                warehouse[count-1].redLineReached+=new RedLineEvent(CallEvent);
             }
        }
     
        private void CallEvent(object sender,EventArgs e)
        {
             if(redLineReached != null)
                     redLineReached(sender,e);
         }
    }
    Merci

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    ça me semble correct !

  12. #12
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2007
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2007
    Messages : 257
    Par défaut
    Ok sinon une dernière question et j'arrête d'embêter.
    Dans le design pattern Observer,à ce que j'ai compris,la classe observatrice doit conserver une instance du type de la classe observée pour pouvoir ajouter une des ses fonctions à l'événement de la classe observée en utilisant une fonction Attach par exemple ne prenant aucun argument;seulement je voulais savoir pourquoi cela est fait comme ça,si cette instance de classe observée n'est pas présente dans la classe observatrice,on pourrait quand même ajouter une fonction de la classe observatrice à l'événement de la classe observée,en passant un paramètre de type classe observée à la fonction Attach; donc est ce qu'au final il y a plusieurs possibilités pour la structure du design pattern Observer ou est ce que il faut privilégier celle ci pour des raisons de stabilité,bug,etc...?

    Merci

  13. #13
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par Miko95 Voir le message
    Dans le design pattern Observer,à ce que j'ai compris,la classe observatrice doit conserver une instance du type de la classe observée pour pouvoir ajouter une des ses fonctions à l'événement de la classe observée en utilisant une fonction Attach par exemple ne prenant aucun argument;seulement je voulais savoir pourquoi cela est fait comme ça,si cette instance de classe observée n'est pas présente dans la classe observatrice,on pourrait quand même ajouter une fonction de la classe observatrice à l'événement de la classe observée,en passant un paramètre de type classe observée à la fonction Attach; donc est ce qu'au final il y a plusieurs possibilités pour la structure du design pattern Observer ou est ce que il faut privilégier celle ci pour des raisons de stabilité,bug,etc...?
    Non, la classe observatrice n'a pas besoin de conserver une instance de la classe observée. Elle n'a besoin de cette instance qu'au moment de s'inscrire à l'évènement. La conséquence est qu'en revanche, la classe observée aura une référence vers la classe observatrice, pour pouvoir l'appeler.
    Par contre, pas besoin pour les 2 classes de connaitre le type réel de l'autre : on peut faire ça avec des interfaces pour faire abstraction du type réel

  14. #14
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2007
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2007
    Messages : 257
    Par défaut
    Merci beaucoup pour toutes les réponses!!

    A bientot

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. design pattern observer vs event
    Par maa dans le forum C#
    Réponses: 5
    Dernier message: 17/12/2007, 16h24
  2. Design Pattern Observer
    Par BoBy9 dans le forum Logging
    Réponses: 1
    Dernier message: 18/11/2007, 19h16
  3. Design pattern Observer
    Par aicfr dans le forum Logging
    Réponses: 1
    Dernier message: 06/11/2007, 23h14
  4. [Conception] Design Pattern Observer Java
    Par jeb001 dans le forum Général Java
    Réponses: 4
    Dernier message: 02/05/2007, 23h43
  5. [Observateur] Précisions sur le design pattern Observer [UML]
    Par joquetino dans le forum Design Patterns
    Réponses: 2
    Dernier message: 07/10/2004, 22h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo