AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

(Abstract)Factory Pattern und Datentransfer

Ein Thema von Lemmy · begonnen am 4. Sep 2015 · letzter Beitrag vom 5. Sep 2015
Antwort Antwort
Seite 1 von 2  1 2   
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.364 Beiträge
 
Delphi 10.3 Rio
 
#1

(Abstract)Factory Pattern und Datentransfer

  Alt 4. Sep 2015, 11:34
Hallo zusammen,

sorry für das lange Posting.... Und gleich der Hinweis: Ich stecke noch in Delphi 7 fest - ich denke mit Generics wäre das einfach zu lösen..

ich versuch eine AbstractFactory zu implementieren, scheitere jedoch an den Details...

Ausgangslage:

Ich habe div. unterschiedliche PDF-Formulare zu füllen, als Beispiel:

* Bestellformular Firma A
* Bestellformular Firma B
* Reklamationsformular Firma C

jedes dieser Formulare liegt zudem in einer bestimmten Version vor, die ab einem bestimmten Datum eingesetzt werden muss, Beispiel:

Bestellformular Firma A
* Version 1 gültig ab 1.1.2014
* Version 2 gültig ab 1.8.2014
....

Bislang steckt der Code dafür in einer Klasse (je Formular) drin, die dann je nach Version unterschiedlichen Code ausführt, Beispiel:

Bestellformular Firma A

Delphi-Quellcode:
   ...
  if DruckDatum >= 1.8.2014 then
  begin
    ....
  end else if Druckdatum >= 1.1.2014 then
  begin
   ...
  end
  ..
Das schreit ja quasi nach dem Factory-Pattern. Also mal flugs umgesetzt. Damit das auch schön wird, gleich mit Interfaces gebastelt:

Delphi-Quellcode:

  IFiller = Interface
  ['{7F30E379-DC1F-433B-9C56-B79D5BDEC356}']
    procedure FillPDF;
  end;

  TFillerClass = class of TPDFFiller;

  TPDFFiller = class(TInterfacedObject, IFiller)
  public
    procedure FillPDF; virtual; abstract;
  end;

  TBestellformularFirmaA = class(TPDFFiller)
  public
  end;

  TBestellformularFirmaA_201401 = class(TBestellformularFirmaA)
  public
    procedure FillPDF; override;
  end;

  TBestellformularFirmaA_201408 = class(TBestellformularFirmaA)
  public
    procedure FillPDF; override;
  end;

  TFillerFactory = class(TObject)
  ....
  public
    procedure RegisterFiller(AClass: TFillerClass; AValidSince, AValidUntil: TDateTime);
    function GetFiller(AFiller: TFillerClass; ADate: TDateTime): IFiller;
  end;

Bei der Factory kann ich dann konkrete Implementierungen hinterlegen und dann in Abhängigkeit von einem Datum anfordern:

Delphi-Quellcode:
  FFactory.RegisterFiller(TBestellformularFirmaA_201401, StrToDate('1.1.2014'), StrToDate('31.7.2014'));
  FFactory.RegisterFiller(TBestellformularFirmaA_201408, StrToDate('1.8.2014'), StrToDate('31.12.2099'));

  ...

  Filler := FFactory.GetFiller(TBestellformularFirmaA, now);
So weit sind im Grunde auch alle Beispiele die ich zu dem Thema bisher gefunden habe


Mein Problem: Wie bekomme ich jetzt Daten in den "Filler"?

Lösung 1:
in die Basisklasse TBestellformularFirmaA kommen alle notwendigen Felder. Der Rückgabewert bleibt jedoch ein IPDFFiller, ein direkter Cast geht in Delphi 7 noch nicht. Hier müsste ich dann eine Funktion einbauen, die mir die Instanz der konkreten Implementierung zurück gibt, und dann nach der Abfrage einen Cast machen:

Delphi-Quellcode:
var PDF: TBestellformularFirmaA;
  Filler := FFactory.GetFiller(TBestellformularFirmaA, now);
  PDF := TBestellformularFirmaA(Filler.GetInstance);
"fühlt" sich aber irgend wie nicht so richtig an...

Lösung 2:
man könnte natürlich argumentieren, dass der PDFFiller eigentlich nichts mit den Nutzdaten zu tun haben sollte, d.h. dass es hier eine Datenhaltungsklasse geben müsste, die Datenfelder also nicht in TBestellformularFirmaA definieren sondern z.B. in TBestellformularFirmaA_Data - nur dann müsste ich im PDFFiller wieder eine Möglichkeit haben bel. Daten zu übergeben, dazu fällt mir aber auch wieder nur ein Typecast ein:

Delphi-Quellcode:
  
  IFiller = Interface
  ['{7F30E379-DC1F-433B-9C56-B79D5BDEC356}']
    procedure FillPDF(IData: Interface);
  end;
um das dann wieder in der konkreten Implementierung zu casten. Sieht mir aber auch nicht "richtig" aus.

Lösung 3: Für jedes Formular eine eigene Factory bauen - das wäre mit Generics nach meinem Empfinden recht einfach zu realisieren, in Delphi7 aber mit deutlich mehr Code und dem Aufwand in jeder Factory dann wieder casten zu müssen


Und jetzt meine Fragen:

* gibt es noch ALternativen bzw. was mich eigentlich bewegt: Was habe ich am Factory-Pattern nicht verstanden?

Grüße
  Mit Zitat antworten Zitat
Benutzerbild von frankyboy1974
frankyboy1974

Registriert seit: 7. Apr 2015
Ort: SH
169 Beiträge
 
Delphi XE7 Professional
 
#2

AW: (Abstract)Factory Pattern und Datentransfer

  Alt 4. Sep 2015, 12:45
Zitat:
Was habe ich am Factory-Pattern nicht verstanden?
Java ist auch eine Insel.
Ist Delphi von Oracle?
In meiner Buchstabensuppen fehlt das C++!
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: (Abstract)Factory Pattern und Datentransfer

  Alt 4. Sep 2015, 12:48
Wenn es immer die gleichen Daten sind, dann benötigst du so etwas
Delphi-Quellcode:
TData = class
  // alle benötigten Eigenschaften
end;

IFilledForm = interface
['{GUID}']
// was soll man mit dem ausgefüllten Formular machen können?
  procedure SendAsEmail( ... );
end;

IFillData = interface
['{GUID}']
  function WithThis( AData : TData ) : IFilledForm;
end;
Die Factory würde ich eher so aufbauen
Delphi-Quellcode:
TFillDataFactory = class
public
  procedure RegisterForm( AFillData : IFillData; const AAspect : string; AValidSince : TDateTime );

  function GetFillData( const AAspect : string; ADate : TDateTime ) : IFillData;
end;
Und aufgerufen wird das dann mit
Delphi-Quellcode:
MyFillDataFactory
  .GetFillData( CurrentCompany.Id, Now() )
  .FillData( TheData )
  .SendAsEmail( ... );
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.364 Beiträge
 
Delphi 10.3 Rio
 
#4

AW: (Abstract)Factory Pattern und Datentransfer

  Alt 4. Sep 2015, 12:59
Wenn es immer die gleichen Daten sind, dann benötigst du so etwas

sind sie leider nicht. Also pro Formular schon, nur möchte ich in einer Factory eben die komplette Bandbreite an Formularen erschlagen, so kann es anstelle eines Bestellformulars halt auch mal (um extrem zu werden) ein Antrag auf Harz IV sein


Die Factory würde ich eher so aufbauen
Delphi-Quellcode:
TFillDataFactory = class
public
  procedure RegisterForm( AFillData : IFillData; const AAspect : string; AValidSince : TDateTime );

  function GetFillData( const AAspect : string; ADate : TDateTime ) : IFillData;
end;
hmmm.. warum einen String für die Unterscheidung verwenden? Eine Elternklasse von der konkrete Implementierungen abgeleitet sind erscheinen mir an der Stelle zweckmäßiger...
  Mit Zitat antworten Zitat
alda

Registriert seit: 24. Mär 2014
Ort: Karlsruhe
93 Beiträge
 
Delphi XE6 Architect
 
#5

AW: (Abstract)Factory Pattern und Datentransfer

  Alt 4. Sep 2015, 13:11
hmmm.. warum einen String für die Unterscheidung verwenden? Eine Elternklasse von der konkrete Implementierungen abgeleitet sind erscheinen mir an der Stelle zweckmäßiger...
Worauf Dich SirRufo hinweisen will ist, dass Du eine harte Kopplung zwischen Implementierung und Factory hast (in dem GetFillData eine konkrete Klasse benötigt). Das Ziel ist ja, dass der Factory-Nutzer nicht wissen muss welche Implementierung hinter dem Interface IFillData steckt.
Des Weiteren macht eine Basisklasse TPDFFillData, die lediglich das Interface IFillData implementiert und die zu implementierenden Methoden als abstract an seine Spezialisierungen weitergibt, so auch keinen Sinn. Ein Interface definiert eine gemeinsame Schnittstelle und eine Klasse eine gemeinsame Vorgehensweise. Die gemeinsame Vorgehensweise ist hier m.E. nicht gegeben und so sollte jede Deiner Implementierungen selbst das Interface IFillData implementieren - eine Vererbungshierarchie ist hier Fehl am Platz.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: (Abstract)Factory Pattern und Datentransfer

  Alt 4. Sep 2015, 13:13
Nein, das ist definitiv nicht zweckmäßiger ... dann wirst du wohl eher so etwas benötigen
Delphi-Quellcode:
IFillData = interface
end;

IFillConcreteData = interface( IFillData )
  function WithThis( AData : TConcreteData ) : IFilledForm;
end;

TFillDataFactory = class

function GetFillData( IID : TGUID; ADate: TDateTime; out Intf: IInterface ) : Boolean;
end;
Und der Aufruf dann
Delphi-Quellcode:
var
  Fill : IFillConcreteData;
  ConcreteData: TConcreteData;

if MyFactory.GetFillData( IFillConcreteData, Now(), Fill ) then
  Fill.WithThis( ConcreteData )
    .SendAsEmail();
Im Prinzip ist es eine erweiterte Supports -Funktion
http://docwiki.embarcadero.com/RADSt...ekt-Interfaces
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 4. Sep 2015 um 13:15 Uhr)
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.364 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: (Abstract)Factory Pattern und Datentransfer

  Alt 4. Sep 2015, 13:19
Worauf Dich SirRufo hinweisen will ist, dass Du eine harte Kopplung zwischen Implementierung und Factory hast
aaahh... das ist natürlich richtig... OK, dann werde ich das umbauen.

Danke euch beiden... wenn ich wieder stolpere, dann schrei ich nochmal laut
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.364 Beiträge
 
Delphi 10.3 Rio
 
#8

AW: (Abstract)Factory Pattern und Datentransfer

  Alt 4. Sep 2015, 14:56
nein, da fehlt bei mir noch ein Baustein:

Wo bekommt denn die Methode GetFillData() dann die Implementierung für ein Interface her? Irgend wo in GetFillData() muss doch dann ein TConcrete.Create() erfolgen...?

Grüße
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: (Abstract)Factory Pattern und Datentransfer

  Alt 4. Sep 2015, 15:32
Schau dir mal das Projekt im Anhang an
Angehängte Dateien
Dateityp: zip FillDataFactory.zip (3,1 KB, 34x aufgerufen)
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.364 Beiträge
 
Delphi 10.3 Rio
 
#10

AW: (Abstract)Factory Pattern und Datentransfer

  Alt 4. Sep 2015, 22:33
nochmals Danke...

aber dann sprechen wir doch streng genommen nicht mehr von einer Factory?!? denn sie verwaltet doch letztlich nur Instanzen die ich nach bestimmten Kriterien abfragen kann....
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

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 14:48 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