AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Problem mit Observer-Pattern

Ein Thema von weltaran · begonnen am 20. Mai 2005 · letzter Beitrag vom 21. Mai 2005
Antwort Antwort
Benutzerbild von weltaran
weltaran

Registriert seit: 12. Sep 2003
Ort: Offenburg
78 Beiträge
 
Delphi 5 Enterprise
 
#1

Problem mit Observer-Pattern

  Alt 20. Mai 2005, 20:21
Hallo Leute!

Ich hab auf der Seite von Joanna Carter das (meines Erachtens sehr gute) Tutorial gelesen. Dennoch habe ich Probleme damit. Der ClockTimer wird einfach so zerstört, ohne das ich dies explizit befohlen habe. Das schein mit der Interface Referenzzählung zusammenzuhängen, aber ganau steig ich da nicht dahinter.

Sorry, dass ich euch da so`n Brocken Code da hinklatsche. Ich tippe stark auf die Notify-Methode, hier müsste der Hund begraben liegen. Ach ja: Ich hab IInterface (kennt mein D5 nicht) durch IUnknown ausgetauscht. Könnte das der Fehler sein?

Delphi-Quellcode:
unit frmMain;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  extctrls, StdCtrls;

type
  TClockTimer = class;
  TForm1 = class;
  TObservable = class;
  IClockTimer = interface;
  TDigitalClock = class;

  IObserver = interface;
  IObservable = interface;

  IObserver = interface
  ['{202BAB74-E7A6-4FEC-9F93-8D3EA8B07172}']
    procedure obsUpdate(const Observable: IUnknown);
  end;

  IObservable = interface
  ['{31F285F0-B80B-479D-BC35-475E6ED8A148}']
    procedure obsAddObserver(observer: IObserver);
    procedure obsDeleteObserver(observer: IObserver);
    procedure obsNotify;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    fClockTimer: TClockTimer;
    fDigitalClock1: TDigitalClock;
  public
  end;

  TObservable = class(TInterfacedObject, IObservable)
  private
    fController: Pointer;
    fObservers: TInterfaceList;
    procedure obsAddObserver(Observer: IObserver);
    procedure obsDeleteObserver(Observer: IObserver);
    procedure obsNotify;
  public
    constructor Create(const Controller: IUnknown);
  end;


  IClockTimer = interface
  ['{9DC95238-36BD-4595-8DE2-B56579A51FC8}']
    function GetTime: TDateTime;
  end;

  TClockTimer = class(TInterfacedObject, IClockTimer, IObservable)
  private
    fTimer: TTimer;
    fInternalTime: TDateTime;
    fObservable: IObservable;
    function GetTime: TDateTime;
    procedure Tick(Sender: TObject);
    property Observable: IObservable read fObservable write fObservable implements IObservable;
  public
    constructor Create;
    destructor Destroy; override;
  end;

  TDigitalClock = class(TPanel, IObserver)
  private
    procedure IObserver.obsUpdate = ObserverUpdate;
    procedure ObserverUpdate(const Observable: IUnknown);
  public
  end;



var
  Form1: TForm1;

implementation

{$R *.DFM}

// TObservable

constructor TObservable.Create(const Controller: IUnknown);
begin
  inherited Create;
  fController:= Pointer(Controller);
end;


procedure TObservable.obsAddObserver(Observer: IObserver);
begin
  if not Assigned(fObservers) then
  begin
    fObservers:= TInterfaceList.Create;
  end;

  fObservers.Add(Observer);
  obsNotify;
end;


procedure TObservable.obsDeleteObserver(Observer: IObserver);
begin
  if Assigned(fObservers) then
  begin
    fObservers.Remove(Observer);
    if fObservers.Count = 0 then
    begin
      fObservers.Free;
    end;
  end;
end;


procedure TObservable.obsNotify;
var
  i: integer;
  myObserver: IObserver;
  myController: IUnknown;

begin
  if Assigned(fObservers) then
  begin
    for i:= 0 to Pred(fObservers.Count) do
    begin
      myObserver:= IObserver(fObservers.Items[i]);
      myController:= IUnknown(fController);
      myObserver.obsUpdate(myController);
    end;
  end;
end;


// TClockTimer

constructor TClockTimer.Create;
begin
  inherited Create;
  fTimer:= TTimer.Create(nil);
  fTimer.Interval:= 1000;
  fTimer.OnTimer:= Tick;
  fTimer.Enabled:= true;
  fObservable:= TObservable.Create(self);
end;

destructor TClockTimer.Destroy;
begin
  //ShowMessage('ClockTimer now destroying!');
  fTimer.Enabled:= false;
  fTimer.Free;
  inherited Destroy;
end;


function TClockTimer.GetTime: TDateTime;
begin
  Result:= fInternalTime;
end;

procedure TClockTimer.Tick(Sender: TObject);
begin
  fInternalTime:= Now;
  fObservable.obsNotify;
end;


// TDigtalClock

procedure TDigitalClock.ObserverUpdate(const Observable: IUnknown);
var
  Obj: IClockTimer;

begin
  Observable.QueryInterface(IClockTimer, Obj);
  if Assigned(Obj) then
  begin
    Caption:= FormatDateTime('tt', Obj.GetTime);
  end;
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
  fClockTimer:= TClockTimer.Create;

  fDigitalClock1:= TDigitalClock.Create(self);

  fDigitalClock1.Parent:= self;
  fDigitalClock1.Align:= alLeft;
  fDigitalClock1.Font.Size:= 14;
  fDigitalClock1.Font.Style:= [fsBold];
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  myObservable: IObservable;
  myObserver: IObserver;
begin
  myObservable:= IObservable(fClockTimer);
  myObserver:= IObserver(fDigitalClock1);

  myObservable.obsAddObserver(myObserver );
end;


end.
Nchtrag: wenn ich die Kommentarzeichen vor ShowMessage wegmache läuft der Zähler los, aber nur wenn ich nach dem Start etwas Zeit vergehen lasse, bis ich auf den Button drücke!

Ciao

weltaran
  Mit Zitat antworten Zitat
Benutzerbild von weltaran
weltaran

Registriert seit: 12. Sep 2003
Ort: Offenburg
78 Beiträge
 
Delphi 5 Enterprise
 
#2

Re: Problem mit Observer-Pattern

  Alt 20. Mai 2005, 21:46
OK, ich hab den Übeltäter jetzt eingekreist. Es handelt sich definitiv um die ObserverUpdate-Methode wenn ich folgenden Code
Delphi-Quellcode:
procedure TDigitalClock.ObserverUpdate(const Observable: IUnknown);
var
  Obj: IClockTimer;

begin

  Observable.QueryInterface(IClockTimer, Obj);
  if Assigned(Obj) then
  begin
    Caption:= FormatDateTime('tt', obj.GetTime);
  end;
end;
durch diesen ersetze
Delphi-Quellcode:



procedure TDigitalClock.ObserverUpdate(const Observable: IUnknown);
var
  Obj: IClockTimer;

begin

  //Observable.QueryInterface(IClockTimer, Obj);
  //if Assigned(Obj) then
  //begin
    Caption:= FormatDateTime('tt', Now);
  //end;
end;


, dann tut alles. Kann mir jemand erklären, was in dieser Funktion vor sich geht?

Bisher habe ich 'QueryInterface' im Zusammenhang mit Schnittstellen noch nie gebraucht. Ist es so, dass ich damit das implementierende Objekt erzeugen kann ohne die Klasse zu kennen? Dann müsste doch in dem Moment, in dem QueryInterface ausgeführt wird auch das Create von TClockTimer ausgeführt werden. Dem scheint aber nicht so zu sein.

Ich wäre für etwas Nachhilfe dankbar.

Ciao



Ciao
This is a signature virus. Copy me to help me spread!
  Mit Zitat antworten Zitat
Lasse2002

Registriert seit: 29. Nov 2004
79 Beiträge
 
RAD-Studio 2009 Pro
 
#3

Re: Problem mit Observer-Pattern

  Alt 21. Mai 2005, 17:17
Du kommst bei der Referenzzählung etws durcheinander, d.h. fClockTimer wird dir zu früh zerstört.

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  myObservable: IObservable;
  myObserver: IObserver;
begin
  myObservable:= fClockTimer;
  fClockTimer._AddRef;
  myObserver:= fDigitalClock1;

  myObservable.obsAddObserver(myObserver);
end;
Lasse
  Mit Zitat antworten Zitat
Benutzerbild von weltaran
weltaran

Registriert seit: 12. Sep 2003
Ort: Offenburg
78 Beiträge
 
Delphi 5 Enterprise
 
#4

Re: Problem mit Observer-Pattern

  Alt 21. Mai 2005, 19:54
Super! Jetzt tut es.

Danke

Ciao
This is a signature virus. Copy me to help me spread!
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:54 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz