Design pattern observer : implémentation réutilisable

Soyez le premier à donner votre avis sur cette source.

Vue 19 948 fois - Téléchargée 2 274 fois

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 / Exemple :


{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.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

paulatreides
Messages postés
1
Date d'inscription
mardi 21 octobre 2003
Statut
Membre
Dernière intervention
12 juin 2008
-
Il y a un composant teechart de steema dans ce programme...
et j'ai pu le compiler et l'exécuter avec turbo explorer
(alors qu'un autre prog avec ce même composant j'ai pas pu)
C'est étrange... Quelqu'un à une explication ?

Merci
DeltaFX
Messages postés
459
Date d'inscription
lundi 19 avril 2004
Statut
Membre
Dernière intervention
8 avril 2009
1 -
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 ?
cs_Delphiprog
Messages postés
4580
Date d'inscription
samedi 19 janvier 2002
Statut
Modérateur
Dernière intervention
9 janvier 2013
24 -
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.
DeltaFX
Messages postés
459
Date d'inscription
lundi 19 avril 2004
Statut
Membre
Dernière intervention
8 avril 2009
1 -
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 ?
cs_pouicky
Messages postés
30
Date d'inscription
lundi 26 avril 2004
Statut
Membre
Dernière intervention
4 août 2010
-
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.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.