![]() |
Problem mit eigener Architektur: Zirkulärer Unit-Bezug...
Hallo!
Ich bastel gerade an dem Grundgerüst eines neuen Programms. Man könnte es vielleicht Architektur nennen, aber ganz so ausgereift ist es noch nicht. Die Idee ist, dass ich im Prinzip die verschiedenen Aufgaben im Programmfluss auf verschiedene Klassen aufteile. Hierbei gibt es eine Hierachie mit zwei Stufen: Auf obersten Stufe arbeitet der ProgramManager, dieser verwaltet einige globale Werte und zudem verschiedene SubManager die Teilaufgaben erledigen. So kümmert sich z.B. der OptionsManager darum, dass die Optionen ausgelesen, geändert, geschrieben, etc. werden. Der ProgrammManager erstellt und kontrolliert die SubManager. Das Problem: Geleichzeitig sollen die SubManager auf die globalen Werte des ProgrammManagers zugreifen können. Deswegen muss die Unit des ProgrammManagers die Units der SubManager referenzieren und umgekehrt. Dies für zu einem zirkulären Bezug:
Delphi-Quellcode:
Unit_A
... uses Unit_B; // Notwendig für TOptionsManager... type TProgrammManager = class(TObject) private FOptionsManager: TOptionsManager; FRegistryPfad: String; public constructor Create; RegistryPfad: String read FRegistryPfad; end; ... constructor TProgrammManager.Create; begin FRegistryPfad := '\Ein\Pfad\in\der\Registry\'; // SubManager "OptionsManager" erstellen und verwenden FOptionsManager := TOptionsManager.Create; FOptionsManager.LiesOptionen; end;
Delphi-Quellcode:
Unit B
... uses Unit_A; // Notwendig für TProgrammManager ... type TOptionsManager= class(TObject) private FParrent: TProgrammManager; public constructor Create(aParrent: TProgrammManager); procedure LiesOptionen; end; ... constructor TOptionsManager.Create(aParrent: TProgrammManager); begin // SubManager mit ProgrammManager Parrent erstellen FParrent := aParrent; end; procedure TOptionsManager.LiesOptionen; begin // Mit globalen Werten des ProgrammManager arbeiten OpenRegistryPath(FParrent.RegistryPfad); ... end; Ich finde die Konstruktion eigentlich recht gut, nur leider funktioniert das Ganze wegen dem zirkulären Unit-Bezug nicht. Habt Ihr eine Idee wie ich dieses Problem umgehen kann? Besten Dank Ares |
Re: Problem mit eigener Architektur: Zirkulärer Unit-Bezug..
Eine mögliche Lösung für dieses Problem wäre, eine Schnittstelle für den ProgramManager bereitzustellen. Diese implementiert er und übergibt einen Zeiger auf sich selbst beim Erstellen an den SubManager. Du hast also quasi (beispielhaft) einen IProgramManager, und der TSubManager übernimmt als Konstruktorparameter nicht TProgramManager, sondern IProgramManager. Der Nachteil hierbei liegt darin, dass du die Eigenschaften quasi doppelt pflegen muss (einmal im Interface und einmal in der Implementierung.
Oder aber, wenn es nicht auf Geschwindigkeit oder Typsicherheit ankommt, könntest du auch die Eigenschaftsnamen als String übergeben. Dann bräuchte dieses Interface nur noch zwei, drei Methoden für den Zugriff. Je nachdem, welche Informationen vom ProgramManager der SubManager braucht, kannst du ihm diese vielleicht auch auf anderem Wege zur Verfügung stellen. Wenn es beispielsweise nur eine Handvoll Informationen wie der Registrypfad sind, könnte der ProgramManager diese Information dem SubManager beim Erstellen mitliefern. Alternativ muss das Interface ja nicht alle Eigenschaften des ProgramManager beinhalten, sondern nur die von SubManagern benötigten (wenn es immer dieselben sind). Edit: Noch eine winzige Kleinigkeit: Parent wird mit einem r geschrieben :mrgreen: |
Re: Problem mit eigener Architektur: Zirkulärer Unit-Bezug..
Hallo,
wenn ich das richtig verstanden habe, soll der Programmmanager mehrere SubManager steuern, welche alle aber auch auf den Programmmanager bezug nehmen sollen. Für diesen Fall bietet es sich an, zunächst eine Basisklasse für alle SubManager in der gleichen Unit wie den Programmmanager zu deklarieren. Diese Basisklasse erhält auch schon den Bezug ( FParent) auf den Programmmanager, der ja in allen Submanagern benötigt wird. Da im Interfaceteil nur Bezug auf die Basisklasse genommen wird, kann die Einbindung der Unit_B später im Implementierungsteil erfolgen.
Delphi-Quellcode:
unit Unit_A;
interface type TSubManager= class; TProgrammManager = class(TObject) private FOptionsManager: TSubManager; FRegistryPfad: String; public constructor Create; RegistryPfad: String read FRegistryPfad; end; TSubManager= class(TObject) protected FParent: TProgrammManager; public constructor Create(aParent: TProgrammManager); virtual; end; implementation uses Unit_B; constructor TProgrammManager.Create; begin FRegistryPfad := '\Ein\Pfad\in\der\Registry\'; // SubManager "OptionsManager" erstellen und verwenden FOptionsManager := TOptionsManager.Create; TOptionsManager(FOptionsManager).LiesOptionen; end; constructor TSubManager.Create(aParent: TProgrammManager); begin // SubManager mit ProgrammManager Parent erstellen FParent := aParent; end; end.
Delphi-Quellcode:
unit Unit_B;
interface uses Unit_A; type TOptionsManager= class(TSubManager) public procedure LiesOptionen; end; implementation procedure TOptionsManager.LiesOptionen; begin // Mit globalen Werten des ProgrammManager arbeiten OpenRegistryPath(FParent.RegistryPfad); ... end; end. |
Re: Problem mit eigener Architektur: Zirkulärer Unit-Bezug..
Danke, das werde ich mal probieren!
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:51 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 by Thomas Breitkreuz