begin process at 2008 05 22 21:48:52
1 177 987 membres
633 nouveaux aujourd'hui
13 991 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

DESIGN PATTERN OBSERVER : IMPLÉMENTATION RÉUTILISABLE


Information sur la source

Catégorie :Tutoriaux Classé sous : design, pattern, observer, motif, conception Niveau : Expert Date de création : 30/04/2006 Date de mise à jour : 07/05/2006 11:55:04 Vu / téléchargé: 8 984 / 985

Note :
10 / 10 - par 3 personnes
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (23)
Ajouter un commentaire et/ou une note

Description

Comme d’habitude, la source d’inspiration fût le forum Delphi avec cette question :
« Comme d'hab, je me pose une question tordue : Je me demande comment faire pour envoyer un message a toute les forms d'une appli, à partir d'une form secondaire de cette appli. J'ai zieuté le tuto de Delphiprog et deux-3 autres sources mais ça reste fortement nébuleux, ces windowseries »

Je vous propose donc un document présentant le design pattern observateur et sa mise en oeuvre concrète par le biais d'une application simple mais pas simpliste.

Le code source n'est volontairement pas commenté. Reportez-vous au document pdf joint à l'archive.
D'ailleurs, il est fortement recommandé de lire ce document en premier AVANT d'aborder le code source.

Je répondrai aux questions sur la mise en oeuvre de ce design pattern. Toutes autres questions ayant trait au design et/ou aux composants graphiques utilisés seront classées sans suite.

Je vous souhaite une bonne lecture.

Source

  • {Didacticiel + code source + modélisation sont dans l'archive}
{Didacticiel + code source + modélisation sont dans l'archive}

Conclusion

L'utilisation de ce code exige les pré requis suivants :
1. maîtrise de la conception objet
2. solides connaissances du concept d’interface et de leur utilisation

L'ensemble des documents n'est pas destiné à un public débutant ou non averti.
Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

30 avril 2006 14:24:23 :
Ajout du diagramme de classes complet pour la station météo.
07 mai 2006 11:55:04 :
1- Correction du code suite à la remarque de Pouicky (merci à lui) 2- ajout de commentaires dans le code suite à vos demandes 3- mise à jour du didacticiel : remarque au sujet de .Net + ajout d'un sommaire
  • signaler à un administrateur
    Commentaire de DeltaFX le 30/04/2006 14:03:06

    Bonne idée les prérequis, étant passablement rouillé niveau POO et total-noob niveau interface, j'ai ramé un poil à l premiere lecture du source :) Forcément, apres avoir révisé, ca passe mieux.

  • signaler à un administrateur
    Commentaire de f0xi le 30/04/2006 22:29:23 administrateur CS

    du beau, du costaud ...

    un bel exemple pour apprécier les possibilitées des interfaces, a analyser a tete reposée.

    cependant, le code manque de commentaires ou alors ils n'apparraissent pas dans l'editeur du site.
    mais bon, vus le publique auquel il s'adresse, plus l'aide PDF fournie qui est de la meilleure qualitée.

    cela merite un 20/10 ...

  • signaler à un administrateur
    Commentaire de f0xi le 30/04/2006 22:31:56 administrateur CS

    si je puis faire une petite suggestion, on pourrais par exemple, a defaut de commentaire dans le source mettre un simple {voir chapitre X de l'aide}
    sur les points importants, ne trouve tu pas ?

    mais ça me semble un peu ... brumeux a faire ...

  • signaler à un administrateur
    Commentaire de Delphiprog le 30/04/2006 23:42:58 administrateur CS

    Merci pour vos remarques et suggestions.

    Foxi : le pdf explique les points esentiels du code et la démarche suivie. De plus, j'ai pris la précaution d'écrire sur cette page web : "Le code source n'est volontairement pas commenté. Reportez-vous au document pdf joint à l'archive."

    Mais, comme tu l'as dit, c'est du costaud. :o)

  • signaler à un administrateur
    Commentaire de John Dogget le 01/05/2006 03:13:57

    Moi aussi ça me semble un peu (beaucoup) brumeux :/
    Si c'est utile pour un professionnel, un amateur n'y trouvera certes pas son compte, c'est bien trop compliqué.
    C'est d'ailleurs pas ça qui l'empechera de pondre une petite appli parfaitement fonctionnelle.

  • signaler à un administrateur
    Commentaire de pouicky le 01/05/2006 12:27:40

    Un super tuto qui élève l'esprit sur des horizons plus larges

    J'en avais vu qui expliquaient la méthodologie Composition ou bien le méthodologie interface, mais là tout s'éclaire. Cependant, je me penche en ce moment sur MVC plus prisé en langages web, mais qui me semble tres lié au pattern observer. J'espere que le probleme que je pose maintenant tombe à propos:
    Mon but est de faire une appli qui puisse changer de base de données avec un minimum d'efforts. (exemple Le SQL de Oracle et le SQL d'access, qui ne sont pas les mêmes).
    Je pense décomposer l'appli en trois parties (Modele-Vue-Controleur:
    1- Une classe de composants d'acces aux données (un module qui pourrait etre interchangé selon le sgbd et/ou l'architecture) - Le Modèle
    2- Les objets "métiers" qui appelleraient des methodes de cette classe d'acces aux données (composition de composants)-Le controleur
    3- Les formulaires qui observeraient les objets métiers, et implementeraient l'ergonomie- la vue

    Or tout ce petit monde serait sujet et observateur des autres.
    L'interface devrait se tenir au courant de l'état de la base de données et de l'état des objets métiers
    Les objets doivent se tenir au courant de l'état de la base et de l'interface lorsque l'utilisateur agit.
    Il y aura les acces aux données faits par les objets métiers
    Il y aurait les acces aux données par les fiches (dbgrid relié par exemple) (pas tres souhaitable dans l'optique MVC)
    Il y aurait autant de commandes sql à envoyer que d'objets modifiés + le retour des resultats à gérer.

    Questions:
    -Doit-on limiter les rôles sujets observateurs au minimum pour les performances ou cela altere t'il tres peu la fluidité d'une appli.?
    -Les meilleurs choix sont il de "mapper les tablesBDD avec des composants DBTables ou plutôt d'utiliser un composant par type d'action :Objet"command", objet "Query" qu'on réutiliserait pour les differents acces??

    Je n'aime pas trop les datamodules pleins de TABLES avec Maitre/esclave qui semblent trop proches de la base.
    Dans quelles mesures peut on compter sur la puissance des composants BDD de delphi pour refléter l'état des données?
    N'ayant pas d'expérience sur le sujet, quelqu'un peut-il m'indiquer une piste?

  • signaler à un administrateur
    Commentaire de cirec le 01/05/2006 14:06:37 administrateur CS

    Salut,
    eh ben que dire ...
    C’est tout simplement génial
    L’exemple est bien fait et le PDF (pour m'a part) m'a apporté la lumière nécessaire à la compréhension du code (il faut absolument lire le PDF en premier)
    Du coup j'ai téléchargé les deux exemples disponibles sur le site et j'ai une petite question :

    Dans l'autre exemple vous parlez de Model Maker que je n'ais pas trouvé.
    Alors est il uniquement disponible avec D7 pro ?
    Je possède un D4 Pro et j'ai eu accès à un D9 Pro mais pas de trace de Model Maker.

    Merci pour ce code, ça ouvre de nouvelles perspectives.
    20/10 Bravo

    @+
    Cirec

  • signaler à un administrateur
    Commentaire de Delphiprog le 01/05/2006 19:25:35 administrateur CS

    Cirec :
    Tu as suivi les recommandations et tu as bien fait.
    Je ne pouvais pas, à la simple lecture du code source, vous montrer la démarche qui fût la mienne. C'est en cela que les outils de modélisation comme UML apportent un plus en se situant au dessus du code source.

    Model Maker fût livré avec Delphi 7. Ce n'est pas indispensable de l'avoir mais c'est bien utile quand même.
    En passant, Model Maker permet l'application de certains design patterns dont l'observateur. Un conseil, n'utilisez pas le code généré, vous vous enfermeriez dans une hiérarchie de classes.

    Les versions .Net de Delphi sont maintenant livrées avec ToGether.
    Notez aussi que ce genre d'outil n'est pas livré avec les éditions perso.

    Que Pouicky me pardonne, mais ses questions appellent des réponses plus développées et je lui consacrerai le temps nécessaire un peu plus tard.

    Je sens qu'on va avoir un vrai débat de passionnés !

  • signaler à un administrateur
    Commentaire de shining le 01/05/2006 21:31:46

    Les patterns Observer et MVC
    http://www.toutenligne.com/index.php?contenu=mvc&menu=pattern

    Choice Pattern
    http://www.swissdelphicenter.ch/en/showcode.php?id=1097

    ModelMaker
    http://www.modelmakertools.com/modelmaker/index.html

  • signaler à un administrateur
    Commentaire de pouicky le 01/05/2006 21:57:52

    Dans l'exemple, il ya 2 fiches Releves et Stats prévues pour observer, et ayant un constructeur qui enregistre leur membre observateur aupres du sujet observable passé en parametre.

    Or l'exemple illustre 2 manieres de gérer l'inscription des observateurs au sujet : Pour la fiche de stat, c'est la fiche principale qui l'inscrit sur son propre FObservable. Alors que pour la fiche de releves c'est le constructeur qui inscrit la fiche sur le membre FObservable de la fiche relevé (j'essaie de résumer, et on est bien d'accord que les membre FOBservables des deux fiches sont le même objet, non?).
    N'y a t'il pas alors deux inscriptions pour la fiche de stats?
    pour verifier cela j'ai saisi testé cela dans l'unité Uobservable

    procedure TObservable.AddObserver(Obs: IObserver);
    begin
      if FObservers.IndexOf(Obs) = -1 then
        FObservers.Add(Obs);
        ShowMessage(inttostr(fobservers.Count));
    end;

    procedure TObservable.RemoveObserver(Obs: IObserver);
    begin
      if FObservers.IndexOf(Obs) <> -1 then
        FObservers.Remove(Obs);
        ShowMessage(inttostr(fobservers.Count));
    end;
    et il y a  un truc bizarre : le clic sur "listing" est cohérent mais le clic sur "statistiques" provoque deux passages dans AddObservers et avec la meme valeur pour Fobservers.count (s'enregistre sans incrementation?? ya t'il une transmission sans traitement de la liste des observateurs entre la fiche principale et la fiche de stats?)

  • signaler à un administrateur
    Commentaire de Delphiprog le 01/05/2006 22:42:51 administrateur CS

    Ta remarque est tout à fait exacte. Heureusement que la méthode AddObserver vérifie la liste avant d'ajouter un observateur. De ce fait, le nombre d'éléments dans la liste n'est pas incrémenté deux fois mais une seule.
    Tu peux donc supprimer ou mettre en commentaire la ligne :
    FObservable.AddObserver(StatsMeteoForm);
    dans la fiche principale.

    Félicitations pour ta perspicacité.
    Quant à moi...:o(

  • signaler à un administrateur
    Commentaire de Delphiprog le 01/05/2006 22:57:42 administrateur CS

    Shining : j'ai jeté un oeil sur les liens que tu as donné. L'implémentation du dp observer repose sur l'utilisation de l'interface Observable fournie par Java.
    Delphi n'en disposant pas (je suis d'accord qu'on peut facilement la reproduire) et comme il est bon de comprendre les principes qui sous tendent, le code fourni ici permet de mieux saisir les mécanismes en jeu.

    J'ai oublié de mentionner dans le tuto que Delphi pour .Net proposait le multicast, variante du dp observer. On peut en parler, mais il n'y aurait pas grand chose à dire puisque tout est déjà fait, un peu comme en Java.

    Quant au choice pattern, s'il est présenté comme plus léger que le strategy pattern, l'exemple fourni ne démontre rien à mon avis puisque l'on appelle séquentiellement chacune des interfaces IChoicePattern au lieu de faire le bon choix comme dans le cas du strategy design pattern.

  • signaler à un administrateur
    Commentaire de Francky23012301 le 02/05/2006 00:40:25

    Bon j'ai pas tout compris à ta source vu le niveau mais je dis quand meme : "CHAPEAU MONSIEUR". C'est sans aucun doute du grand art.

    Le plus dingue c'est quant te connaissant je suis sur que tu as fais ca en meme pas 1h. Aurais tu avant fais la fameuse incantation de fOxi ??

  • signaler à un administrateur
    Commentaire de shining le 02/05/2006 21:34:18

    Oui en effet DelphiProg, le ChoicePatterne quant à lui est assez limité dans ses possibilités et l'exemple choisit n'est pas vraiment très reprensative du choice pattern !!, allez pour me faire pardonner voici un lien très intérréssant à ne pas rater, qui d'une certaine façon pourrait-être un complément d'info à ce superbe tutoriel !!!

    de la Strategy à l'Iterator tout y est ou presque !!!

    http://www.felix-colibri.com/papers/design_patterns/the_lexi_editor/the_lexi_editor.html
    @+

  • signaler à un administrateur
    Commentaire de shining le 02/05/2006 21:36:11

    oula c'est quand qu'on pourra editer nos messages ? et retiré les vilaines fautes d'orthographes ? lol

  • signaler à un administrateur
    Commentaire de Delphiprog le 03/05/2006 00:11:14 administrateur CS

    Tu n'as pas choisi n'importe qui comme référence. John COLIBRI est une référence !
    Je connaissais son site mais je ne le trouve pas facile à lire. C'est un avis personnel.
    Les ouvrages que j'ai cité dans la partie bibliographie sont tous publiés en langue française et ça aide pour bien comprendre les patterns et les maîtriser.

    Shining : de même qu'il faut tourner sept fois sa langue dans bouche avant de parler, mieux vaut se relire deux fois avant de cliquer sur le bouton "ajouter votre commentaire", lol.
    ++

  • signaler à un administrateur
    Commentaire de shining le 04/05/2006 20:39:38

    Lol !!!,non en fait je n'ai qu'une petite fenêtre contrairement à vous , qui avez plus de possibilités avec la fenêtre avancée !!!, je suppose que le site fait appel à la java virtual machine où quelque chose comme ça !!! mais bon c'est aussi de mon habitude de faire des fautes :] ça fait fashion parait-il !!!
    le ScreenShot me fait penser à ESS MODEL pour faire des diagrammes en UML
    c'était jadis un projet commercial, qui par la suite est devenu OpenSource à voir et à télécharger absolument !!!
    http://essmodel.sourceforge.net/screenshots.html

  • signaler à un administrateur
    Commentaire de Delphiprog le 07/05/2006 12:02:38 administrateur CS

    Je viens de mettre à jour le code ainsi que le pdf en espérant que cela sera moins "brumeux" pour certains :o)

    C'est sûr que quand on parle architecture logicielle, mieux vaut avoir l'esprit clair et un minimum d'expérience dans ce domaine.

    Pouicky, je ne t'oublie pas, mais...

    L'urgent est déjà parti,
    L'impossible est en train de se faire,
    Pour les miracles, je demande un délai !

  • signaler à un administrateur
    Commentaire de pouicky le 07/05/2006 15:49:39

    Que tu t'interesses à la question est dejà super. Je m'aperçois en effet que pour ce qui est des données, le pattern observer a d'autre implications. Et je me prépare à poster une source sur la réutilisation du code et découplage entre objets et interface dans une application simple en delphi (elle sera imparfaite, et illustrera donc les problemes posés, et peut-etre d'autres)
    j'attends tes pistes avec impatience ;). Ce qui manque plus que la technique sur ces problemes c'est l'expérience et j'en manque cruellement.

  • signaler à un administrateur
    Commentaire de pouicky le 08/05/2006 21:49:45

    j'ai planché et ai buté sur des impasses dans le cas du pattern observer avec sgbd. Puis je me suis aperçu qu'avec la vcl et ses controles de données, on fait du pattern observer sans le savoir. J'ai essayé de jouer avec les datamodules et les composants ado et ai posté un code qui illustre deux manieres d'utiliser les datamodules pour des comportement "observer" ou "non observer". Je ne sais pas si c'est dans les "bonnes pratiques" mais ça permet de reflechir.. http://www.delphifr.com/codes/UTILISATION-DATAMODULES-VCL-POUR-IMPLEMENTER-PATTERN-OBSERVER-OU_37511.aspx

  • signaler à un administrateur
    Commentaire de DeltaFX le 28/11/2006 15:18:03

    Petite question de la part du noob de service. Autant je saisis bien tout , autant je me demande encore ce que sont et à quoi servent les series alphanumériques dans les codes des interfaces IMeteo, IObservables & IObserver ?

    IMeteo = interface
        ['{83EF5DD2-9F1D-4BE9-8F97-57BE0BDED25C}']
    ...

    IObservable = interface
        ['{B72C935C-4E37-405F-B778-1C507A8F8BB9}']
    ...

    IObserver = interface
        ['{8B1211C7-5799-486F-A66C-EF999D087229}']
    ...


    Seraient-ce des clefs de registre (ça y ressemble...) ? Comment les choisit-on ?

  • signaler à un administrateur
    Commentaire de Delphiprog le 28/11/2006 23:36:52 administrateur CS

    Question très pertinente mon cher DeltaFx !

    Dans le code source proposé ici, on peut dire que les identifiants uniques des interfaces utilisées ne servent à rien.

    En revanche, c'est une bonne habitude de les utiliser si tu dois faire usage de la méthode QueryInterface ou de la fonction Supports qui réclament un identifiant d'interface (IID).

    C'est aussi important si tu crées un serveur automation qui a besoin d'être enregistré sur une machine pour être appelé. La base de registres de Windows en est remplie.

    On ne choisit pas le contenu des clés mais on l'obtient :
    - soit par la combinaison de touches [Shift][Ctrl][G]
    - soit par programmation en appelant la fonction CoCreateGuid déclarée dans ActiveX.pas (ou encore CreateGuid déclarée dans SsyUtils.pas) de la façon suivante :
    var
      Guid: TGUID;
    begin
      CoCreateGuid(Guid);
      Memo1.Lines.Add(GuidToString(Guid));
    end;

    "Autant je saisis bien tout" : ce genre de commentaire fait bien plaisir.
    Merci de porter un intérêt à ce code.

  • signaler à un administrateur
    Commentaire de DeltaFX le 29/11/2006 00:46:07

    Ben un peu que j'y porte de l'interet, tu avais fait ce tuto en réponse à une de mes questions sur le forum. Or, quand je pose une question, c'est que la réponse m'interresse :)


    Donc dans le cadre d'un prog simple, puis-je  les omettre, ces identifiant uniques  ?




    Cette implémentation résoud une partie du problème qui me turlupinait à l'époque (et que j'avais réglé à la barbare-pas trop POO dirons-nous) : faire réagir mes forms (celles qui en ont besoin donc), à une source de données : dans le cas présent une carte interface USB, où en gros quand telle entrée passait à 1, je devais signifier à la form s'occupant de la lecture MP3 de faire un mute, et à celle s'occupant de la camera de recul de passer en plein écran et inversement.

    Ensuite une source composite est apparue : un GPS ( à 1 Hz) fusionné à 2 accéléromèetres 3D ( à 20 Hz), le tout dans un thread, avec 2 filtres de Kalman pour le cas ou le gps ne renvoie rien,le tout en temps réel mou vu que plateforme zindoz : OK, là aussi, interface, et notification de mise a jour de 2 forms.

    Pareil pour le bus CAN-habitacle et les données du tauradio ( faire croire au toradio qu'il a un chargeur cd de branché....) rebelote, interface, pif pouf.

    Là ou ça commence à faire lourd pour mes neurones toutes ces interfaces à la ActionListener Style, c'est qu'en plus, chacune des forms doit écouter aussi la form principale pour les cas de mise en veille du système : procedure PrepareToHibernate, du genre déconnecter la carte USB, fermer le port GPS, interrompre les lectures des acceleromètres, suspendre les threads  etc etc; et sa petite soeur, ResumeFromHibernate qui relance tout ce qui était actif avant.

    Ne nous arretons pas là, paske qu'une partie du prog, via SpeedFan et son segment mémoire partagé, me surveille qqs températures /vitesses de ventilo dans le boitier du pc, et que ce bout de code peut me générer plusieurs niveaux d'alerte, en fonction desquels certaines fonctions se désactivent pour alleger le proc, voir au pire en arriver à balancer un ordre de shutdown au PC.

    Donc une info part de la partie Hardware vers la form principale, qui détermine ce qu'il faut faire et qui elle doit dispatcher des ordres vers les autres forms....

    Ca commence à faire lourd niveau qui observe quoi.  Finalement j'avais résolu le truc en utilisant ça comme modele de Forms :

    unit ExtendedForm;

    interface
    uses
    Forms;

    type
      TExtendedForm = class(TForm)
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
        procedure AnalyseThis(Msg:String;Flag:integer);virtual; // Pas oublier le virtual, très important  !
      end;


    implementation

    { TExtendedForm }

    procedure TExtendedForm.AnalyseThis(Msg:String;Flag:integer);
    begin
       // rien
    end;

    end.

    et en ayant dans l'unit qui gere toute les var globales, les fonctions :


    ...
    implementation

    //-----------------------------------------------------------
    procedure SpreadMsg(aMsg:String;aFlag:integer);
    var i: integer;
    begin
      for i:=NbOfForms downto 0 do
      if FormNames[i]<>'' then
        with FindGlobalComponent(FormNames[i]) as TExtendedForm
        do AnalyseThis(aMsg,aFlag);
    end;

    //-----------------------------------------------------------
    procedure RegisterMe(aName: string;aTag:integer);
    begin
      FormNames[aTag]:=aName;
    end;

    //-----------------------------------------------------------
    procedure UnRegisterMe(aTag:integer);
    begin
      FormNames[aTag]:='';
    end;




    Mais ca restait très séquentiel.... Voila pourquoi je cherchais jadis une forme de communication plus générique, plus dans le style des Post/send Messages windows, donc au choix asynchrone (Fire n'Forget) ou pas.




    ... Voili voilou...

    Tiens au fait, ca existe les Moniteurs en Delphi, les trucs qui permettent de mettre des threads en suspend sur une condition particulière, puis de les réveiller ?

Ajouter un commentaire

Appels d'offres

Pub



Snippets en rapport

CalendriCode

Mai 2008
LMMJVSD
   1234
567891011
12131415161718
19202122232425
262728293031 

VS Express FR Gratuit !

VS Express en français et 100% gratuit !

Téléchargements

Boutique

Boutique de goodies CodeS-SourceS