AGB  ·  Datenschutz  ·  Impressum  







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

Entkoppeln von Forms

Ein Thema von TigerLilly · begonnen am 12. Sep 2017 · letzter Beitrag vom 15. Sep 2017
Antwort Antwort
Der schöne Günther

Registriert seit: 6. Mär 2013
6.114 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

AW: Entkoppeln von Forms

  Alt 12. Sep 2017, 12:04
Vielleicht bin ich schon zu lange im Urlaub, aber was genau soll das Problem sein? Weshalb solltest du Instanzen der Formulare zu Beginn erzeugen müssen? Was ist ein Creatable und was ein Injectable?

Container wie Spring bieten auch an, z.B. Klassen als Singletons registrieren zu können und man bekommt dann, wenn man den Typ (bzw. Schnittstelle anfordert) die entsprechende Instanz.


Vielleicht habe ich auch die Frage noch nicht verstanden, es hörte sich zumindest für mich genauso an wie mein Fall mit z.B. den Input-Popups.
  Mit Zitat antworten Zitat
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
1.179 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Entkoppeln von Forms

  Alt 12. Sep 2017, 12:35
Weil DI wie der Name sagt das Übergeben einer Abhängigkeit ist. Mein FormA müsste also FormB "injected" bekommen. Dann hilft der DI-Container.

Aber wie hast du das mit deinen Input-Popups gelöst?
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Entkoppeln von Forms

  Alt 12. Sep 2017, 15:27
Wir haben das komplett über Interfaces und passende Factories gelöst.

Es gibt also ein Interface für eine bestimme Form z.B

Delphi-Quellcode:
ICncMachineConverterForm = interface
      ['{DC5376B6-B124-4035-B641-6BECAD516DE9}']
      function ShowcheckMarking(const aGetMark: int64; const aContact : tCncContact) : boolean;

   end;
Dann haben wir verschiedene Factories (Die meistens auch Interfaces sind) für unsere Forms

also zB:
Delphi-Quellcode:
TCnFormFactory = class // Static
 class function getICncMachineConverterForm : ICncMachineConverterForm; static;
end;
Im Source dann einfach

Delphi-Quellcode:
iCncForm := TCnFormFactory. getICncMachineConverterForm;
if IcncForm. ShowcheckMarking(14, myContact) then......
Ob die Form nun selber das Interface zur verfügung stellt oder wo auch immer das herkommt ist unwichtig.
Fritz Westermann
  Mit Zitat antworten Zitat
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
1.179 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Entkoppeln von Forms

  Alt 12. Sep 2017, 15:39
Ich hab jetzt mal sowas:

Delphi-Quellcode:
type
  TCreateFormFunction = reference to function(Owner: TComponent): TForm;

  TFormFactory = class
    FList: TDictionary<string, TCreateFormFunction>;
  public
    constructor Create; virtual;
    procedure RegisterForm(sName: String; CreateFormFunction: TCreateFormFunction);
    function CreateForm(sName: String; Owner: TComponent): TForm; virtual;
  end;

implementation

constructor TFormFactory.Create;
begin
  FList := TDictionary<string, TCreateFormFunction>.Create;
end;

function TFormFactory.CreateForm(sName: String; Owner: TComponent): TForm;
begin
  Result := FList[sName](Owner);
end;

procedure TFormFactory.RegisterForm(sName: String; CreateFormFunction: TCreateFormFunction);
begin
  FList.Add(sName, CreateFormFunction);
end;
Damit kann eine eigene Unit, die einzelnen Forms registrieren:
Delphi-Quellcode:
var
  FormFactory: TFormFactory;

implementation

uses
  Form01.View, Form02.View;

procedure Formregistration;
begin
  FormFactory := TFormFactory.Create;
  FormFactory.RegisterForm('Form02',
    function(Owner: TComponent): TForm
    begin
      Result := TForm02.Create(Owner);
    end);
  FormFactory.RegisterForm('Form01',
    function(Owner: TComponent): TForm
    begin
      Result := TForm01.Create(Owner);
    end);
end;
Und mein Form01, der gar nichts von Form02 weiß, kann dieses machen:
  Formfactory.CreateForm('Form02',Self).Show; Das ist doch schon mal nett.

Das verfeinere ich jetzt noch wie folgt:
- Interfaces statt TForms
- Ich will ja nicht x-beliebige Forms registrieren, Sinn hat das ja nur für jene, die das gleiche tun. Also eine eigene factory je Interface.

Mal sehen.

Feedback gerne, danke.
  Mit Zitat antworten Zitat
bepe

Registriert seit: 17. Okt 2006
118 Beiträge
 
#5

AW: Entkoppeln von Forms

  Alt 12. Sep 2017, 18:33
Das sieht ziemlich vertraut aus. Aber zusätzlich ist die Factory bei mir ein Singleton und wenn du keinen abgeleiteten Konstruktor verwendest, wäre mir TCreateFormFunction zu viel Tipparbeit .

Delphi-Quellcode:
interface

uses
  System.Classes,
  System.SysUtils,
  System.Generics.Collections,
  Vcl.Forms;

type
  IFactory = interface
  ['{D91ADAAF-971F-497F-8EDA-A4644BA33087}']
    procedure RegisterForm(AClass: TCustomFormClass);
    procedure UnRegisterForm(AClass: TCustomFormClass);

    function GetInstance(AClass: TCustomFormClass; AOwner: TComponent): TCustomForm; overload;
    function GetInstance(const AClassName: String; AOwner: TComponent): TCustomForm; overload;

  end;

function FormFactory: IFactory;

implementation

type
  TFactory = class(TInterfacedObject, IFactory)
  class var
    FactoryInstance: IFactory;

  class constructor CreateClass;
  class destructor DestroyClass;

  strict private
    FClassList: TDictionary<String, TCustomFormClass>;

  public
    constructor Create;
    destructor Destroy; override;

    procedure RegisterForm(AClass: TCustomFormClass);
    procedure UnRegisterForm(AClass: TCustomFormClass);

    function GetInstance(AClass: TCustomFormClass; AOwner: TComponent): TCustomForm; overload;
    function GetInstance(const AClassName: String; AOwner: TComponent): TCustomForm; overload;

  end;

function FormFactory: IFactory;
begin
  Result := TFactory.FactoryInstance;
end;

{ TFactory }

constructor TFactory.Create;
begin
  inherited;

  FClassList := TDictionary<String, TCustomFormClass>.Create;
end;

class constructor TFactory.CreateClass;
begin
  TFactory.FactoryInstance := TFactory.Create;
end;

destructor TFactory.Destroy;
begin
  FClassList.Free;

  inherited;
end;

class destructor TFactory.DestroyClass;
begin
  TFactory.FactoryInstance := nil;
end;

function TFactory.GetInstance(AClass: TCustomFormClass;
  AOwner: TComponent): TCustomForm;
begin
  Result := GetInstance(AClass.ClassName, AOwner);
end;

function TFactory.GetInstance(const AClassName: String;
  AOwner: TComponent): TCustomForm;
var
  tmpClass: TCustomFormClass;
begin
  if FClassList.TryGetValue(AClassName, tmpClass) then
    Result := tmpClass.Create(AOwner)
  else
    raise Exception.Create('Unbekannte Formklasse');
end;

procedure TFactory.RegisterForm(AClass: TCustomFormClass);
begin
  FClassList.AddOrSetValue(AClass.ClassName, AClass);
end;

procedure TFactory.UnRegisterForm(AClass: TCustomFormClass);
begin
  FClassList.Remove(AClass.ClassName);
end;
Die Registrierung würde ich eher direkt beim Form machen. Sonst wird mal was übersehen oder es kommt eine "riesige" Unit mit unzähligen Abhängigkeiten dabei raus.

Delphi-Quellcode:
  TMyForm = class(TForm)
  class constructor ClassCreate;
  class destructor ClassDestroy;

  end;
...
{ TMyForm }

class constructor TMyForm.ClassCreate;
begin
  FormFactory.RegisterForm(TMyForm);
end;

class destructor TMyForm.ClassDestroy;
begin
  FormFactory.UnRegisterForm(TMyForm);
end;
Und der Aufruf wäre wie gehabt: FormFactory.GetInstance('TMyForm', Self).Show;

mfg,
bp
  Mit Zitat antworten Zitat
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
1.179 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Entkoppeln von Forms

  Alt 12. Sep 2017, 20:24
Ja, das ist auch sehr cool.
Ich glaub, da schau ich mir was ab.

Aber - wenn du erlaubst - ich würde die Interfacedefinition in eine eigene Unit geben. Sonst bindet jede Verwendung des Interfaces die Klasse mit ein.
Und auch die Registrierung direkt beim Form finde ich nicht so super, weil das ja erst wieder die Form an die Factory koppelt. Und ich wollte ja Kontrolle über die Registrierung.

Bei "meiner" Variante sehe ich den Vorteil, dass ich Kontrolle über das Erzeugen des Forms habe - ich könnte hier auch so was machen:

FormFactory.RegisterForm('Form01',
function(Owner: TComponent): TForm
var
tmp:TForm1;
begin
tmp := TForm01.Create(Owner);
tmp.XY:= ....
tmp.DoSomething;
Result:=tmp;
end);

Geändert von TigerLilly (12. Sep 2017 um 20:39 Uhr)
  Mit Zitat antworten Zitat
ayden88

Registriert seit: 15. Sep 2017
1 Beiträge
 
#7

AW: Entkoppeln von Forms

  Alt 15. Sep 2017, 05:31
Weshalb solltest du Instanzen der Formulare zu Beginn erzeugen müssen?
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.012 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#8

AW: Entkoppeln von Forms

  Alt 15. Sep 2017, 09:14
Weshalb solltest du Instanzen der Formulare zu Beginn erzeugen müssen?
Aus demselben Grund, warum man per IDE Forms in die auto-create Liste packen kann?
Für den weitaus üblicheren Fall des "wird erst erzeugt, wenn gebraucht" hab ich ja schon
in beiden meiner vorherigen Kommentare das Schlüsselwort "lazy initialization" erwähnt.

Lazy initialization heißt aber ebend nicht "statische Abhängigkeit, hol dir doch den Krams selbst ab",
sondern: injection der Factory/einer möglichkeit, die Instanz beim ersten Zugriff erst erzeugen zu lassen.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (15. Sep 2017 um 09:17 Uhr)
  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 03:20 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