![]() |
(Abstract)Factory Pattern und Datentransfer
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:
Das schreit ja quasi nach dem Factory-Pattern. Also mal flugs umgesetzt. Damit das auch schön wird, gleich mit Interfaces gebastelt:
...
if DruckDatum >= 1.8.2014 then begin .... end else if Druckdatum >= 1.1.2014 then begin ... end ..
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:
So weit sind im Grunde auch alle Beispiele die ich zu dem Thema bisher gefunden habe :-)
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); 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:
"fühlt" sich aber irgend wie nicht so richtig an...
var PDF: TBestellformularFirmaA;
Filler := FFactory.GetFiller(TBestellformularFirmaA, now); PDF := TBestellformularFirmaA(Filler.GetInstance); 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:
um das dann wieder in der konkreten Implementierung zu casten. Sieht mir aber auch nicht "richtig" aus.IFiller = Interface ['{7F30E379-DC1F-433B-9C56-B79D5BDEC356}'] procedure FillPDF(IData: Interface); end; 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 |
AW: (Abstract)Factory Pattern und Datentransfer
Zitat:
|
AW: (Abstract)Factory Pattern und Datentransfer
Wenn es immer die gleichen Daten sind, dann benötigst du so etwas
Delphi-Quellcode:
Die Factory würde ich eher so aufbauen
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;
Delphi-Quellcode:
Und aufgerufen wird das dann mit
TFillDataFactory = class
public procedure RegisterForm( AFillData : IFillData; const AAspect : string; AValidSince : TDateTime ); function GetFillData( const AAspect : string; ADate : TDateTime ) : IFillData; end;
Delphi-Quellcode:
MyFillDataFactory
.GetFillData( CurrentCompany.Id, Now() ) .FillData( TheData ) .SendAsEmail( ... ); |
AW: (Abstract)Factory Pattern und Datentransfer
Zitat:
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 ;-) Zitat:
|
AW: (Abstract)Factory Pattern und Datentransfer
Zitat:
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. |
AW: (Abstract)Factory Pattern und Datentransfer
Nein, das ist definitiv nicht zweckmäßiger ... dann wirst du wohl eher so etwas benötigen
Delphi-Quellcode:
Und der Aufruf dann
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;
Delphi-Quellcode:
Im Prinzip ist es eine erweiterte
var
Fill : IFillConcreteData; ConcreteData: TConcreteData; if MyFactory.GetFillData( IFillConcreteData, Now(), Fill ) then Fill.WithThis( ConcreteData ) .SendAsEmail();
Delphi-Quellcode:
-Funktion
Supports
![]() |
AW: (Abstract)Factory Pattern und Datentransfer
Zitat:
Danke euch beiden... wenn ich wieder stolpere, dann schrei ich nochmal laut :-) |
AW: (Abstract)Factory Pattern und Datentransfer
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 |
AW: (Abstract)Factory Pattern und Datentransfer
Liste der Anhänge anzeigen (Anzahl: 1)
Schau dir mal das Projekt im Anhang an ;)
|
AW: (Abstract)Factory Pattern und Datentransfer
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.... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:52 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