AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Observer-Pattern Implementation

Observer-Pattern Implementation

Ein Thema von Ghostwalker · begonnen am 10. Nov 2016 · letzter Beitrag vom 11. Nov 2016
 
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#1

Observer-Pattern Implementation

  Alt 10. Nov 2016, 14:40
Im Zuge eines etwas größeren Projekts, hat mich stahli (dicken Dank für deine Gedult und Mühe an der Stelle) auf die Idee gebracht, für meine Anwendung das Observer-Pattern zu nutzen.

Dazu hatte ich einige Vorraussetzungen:

a) Die Implementierung der notwendigen Funktionen sollte möglichs eigentständig sein

Da einiges an Objekten zusammenkommt, wollte ich vermeiden, jedesmal das gleiche
zu machen. Andererseits müssen bei den Unterschiedlichen konkreten Objekten
aber auch unterschiedliche Daten übertragen werden.

b) Da das o.g. Projekt später auch über ein Plugin-System erweiterbar werde wird,
muss auch gewährleistet sein, das ich ggf. Elemente aus einer externen DLL bekomme.


b heißt also Interfaces, da das der mir einzig bekannte Weg ist, sowas wie Objekte
aus einer DLL zu bekommen, bzw anzusprechen.

a heißt, Basisklassen die die Daten als Pointer liefern.

Hier will ich nu meine Implementation präsentieren:

Interface

Delphi-Quellcode:
TYPE
  ISubject = INTERFACE;

  IListener = INTERFACE
    Procedure RegisterMe(Const aSubject:ISubject);
    Procedure UnregisterMe(Const aSubject:ISubject);
    procedure Notification(const data:Pointer);
  END;

  ISubject = Interface
     Procedure RegisterListener(const obj:IListener);
     Procedure UnregisterListener(Const obj:IListener);
     Procedure NotifyListener(const data : Pointer);
  End;
Basisklassen:

Delphi-Quellcode:
unit BaseClasses;

interface
uses
  windows,classes,contnrs,BaseInterfaces;

TYPE
  TBaseSubject = class;

  TBaseListener = class(TInterfacedPersistent,IListener)
  private
  protected
  published
  public
    Procedure RegisterMe(Const aSubject:ISubject);
    Procedure UnregisterMe(Const aSubject:ISubject);
    //Wird erst in der Ableitung befüllt.
    procedure Notification(const data:Pointer);virtual;abstract;
  end;

  TBaseSubject = Class(TInterfacedPersistent,ISubject)
  PRIVATE
     flist : TList;
     procedure ClearList;
  PROTECTED
  PUBLISHED
     Constructor Create;
     Destructor Destroy;override;
  PUBLIC
     Procedure RegisterListener(Const obj:IListener);
     Procedure UnregisterListener(Const obj:IListener);
     Procedure NotifyListener(const data : Pointer);
  End;

implementation

{ TBaseListener }

procedure TBaseListener.RegisterMe(aSubject: ISubject);
begin
  aSubject.RegisterListener(self);
end;

procedure TBaseListener.UnregisterMe(aSubject: ISubject);
begin
  aSubject.UnregisterListener(self);
end;

{ TBaseSubject }

procedure TBaseSubject.ClearList;
begin
  while (flist.count > 0) do
    flist.Delete(0);
end;

constructor TBaseSubject.Create;
begin
  flist := TList.create;
end;

destructor TBaseSubject.Destroy;
begin
  ClearList;
  flist.free;
  inherited;
end;

procedure TBaseSubject.NotifyListener(const data:pointer);
var
  i : integer;

begin
  for I := 0 to flist.count - 1 do
    IListener(flist.items[i]).Notification(data);
end;

procedure TBaseSubject.RegisterListener(obj: IListener);
begin
  flist.Add(Pointer(obj));
end;

procedure TBaseSubject.UnregisterListener(obj: IListener);
begin
  flist.Remove(Pointer(obj));
end;
und schließlich meine "Realen" Klassen aus dem Testprojekt:

Delphi-Quellcode:
uses
  windows,classes,BaseClasses;

TYPE

  TRealListener = Class(TBaseListener)
    PRIVATE
    PROTECTED
    PUBLIC
      procedure Notification(const data:pointer);override ;
    PUBLISHED
  End;

  TRealSubject = Class(TBaseSubject)
    PRIVATE
      fcaption : string;
    procedure setCaption(const Value: string);
    PROTECTED
    PUBLIC
    PUBLISHED
      property Caption:string read fcaption write setCaption;
  End;
implementation
uses
  unit28;

{ TRealListener }

procedure TRealListener.Notification(const data: pointer);
begin
  form28.memo1.lines.append(string(data^));
end;

{ TRealSubject }


procedure TRealSubject.setCaption(const Value: string);
begin
  fcaption := Value;
  NotifyListener(@fcaption);
end;

end.
(unit28 is lediglich die Form der Application mit Buttons und einem Memo drauf )

Außer dem Einsatz von Generics, fällt mir im Moment keine Optimierung mehr ein (und da ich
Turbo Delphi einsetze, geht das im Moment nicht )

Was haltet ihr davon ?
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
 

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 15:07 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz