Hallo,
ich implementiere gerade erstmals eine leichtgewichtige Trennung von Logik und UI. Diese funktioniert bei mir folgendermaßen:
Die Logik ist gekapselt. Jede spezielle Logik-Klasse leitet sich von einer abstrakten Klasse ab, die das Interface zur Benutzung definiert. Diese abstrakte Klasse leitet sich von einer Basisklasse für alle Logiken ab.
Delphi-Quellcode:
TLogicIntf = class(TObject)
// Basisklasse für alle Logiken
end;
TMainIntf = class(TLogicIntf)
// abstrakte Basisklasse für die MainLogic, welche das Interface für die UI definiert
public
procedure Foo; virtual; abstract;
end;
TMain = class(TMainIntf)
// konkrete Implementierung der MainLogic
public
procedure Foo; override;
end;
Für die UI gibt es eine Basisklasse und davon abgeleitet verschiedene spezielle Fenster:
Delphi-Quellcode:
TView = class(TForm)
// Basisklasse für alle Views
strict private
FRestorePos: Boolean;
FRestoreSize: Boolean;
public
// Konstruktoren und Destruktoren
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property RestorePos: Boolean read FRestorePos write FRestorePos
default True;
property RestoreSize: Boolean read FRestoreSize write FRestoreSize
default True;
end;
TMainForm = class(TView)
// erste spezielle View
strict private
FMainLogic: TMainIntf;
strict protected
property MainLogic: TMainIntf read FMainLogic;
public
constructor Create(AOwner: TComponent; AMainLogic: TMainIntf); reintroduce;
end;
Und dann gibt es eine Klasse TLoader, die momentan ein Ladefenster zu Programmstart zeigt und das Hauptfenster und dessen Logik instanziert:
Delphi-Quellcode:
TLoader = class(TForm)
LoadLbl: TLabel;
strict private
FMainForm: TView;
FMainLogic: TLogicIntf;
FWindowsInitialized: Boolean;
protected
procedure DoShow; override;
end;
procedure TLoader.DoShow;
begin
inherited;
if not FWindowsInitialized then
// TAsync.Call: Die anonyme Methode wird aufgerufen, nachdem eine asynchron gesendete Windows-Message angekommen ist, also wenn TLoader tatsächlich sichtbar ist.
TAsync.Call(procedure
var
Handler: TEvtPropBool.TChangedEvt;
begin
if FWindowsInitialized then
Exit;
FWindowsInitialized := True;
LoadLbl.Caption := 'Laden...';
Application.ProcessMessages;
FMainLogic := TMain.Create;
FMainForm := TMainForm.Create(Application, TMainIntf(FMainLogic));
FMainForm.Show;
Hide;
end);
end;
(Quelltext wurde gekürzt)
Bis zur Erstellung des Hauptfensters meiner Anwendung ist also alles klar und ich bin glücklich mit der Vorgehensweise. Da ich aber keinerlei Erfahrungen mit MVC oder ähnlichem habe, stellt sich nun folgende Frage:
Unser Programm stellt im Hauptfenster eine Auswahl an Projekten bereit, mit denen gearbeitet werden kann. Jedes Projekt soll in einem eigenen Fenster angezeigt werden. In die UI (TMainForm) gehört m.E. nur der ButtonClick, der zu dem Projekt gehört, was geöffnet werden soll. Im OnClick wird dann eine Methode der Logik aufgerufen, die das Projekt initialisiert etc. und letztlich auch das Öffnen des neuen Fensters anstoßen sollte. Die Logik kennt natürlich weder die UI noch den Loader (Controller).
Wie funktioniert das Öffnen des neuen Fensters bei solchen Trennungen üblicherweise?
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."