class ProjectConfig {
String owner = "unknown";
Managers managers = new Managers();
}class Managers {
String classLoaderManager = "ds.managers.ClassLoaderManager";
String classManager = "ds.managers.ClassManager";
String instanceManager = "ds.managers.InstanceManager";
}
> >
> > Bist du sicher, dass die Klasse "Managers" statt "Manager" heißen soll? Ich bin leider nicht so sehr in diesem Thema drin, aber so wie du diese Strings speicherst, klingeln bei mir die Alarmglocken.
> So wie oben zusehen, sind die zugewiesenen Strings eigentlich nur die Standard-Einstellungen, quasi würde das Programm erst ProjectConfig instantiieren, dann die eigentliche Projektkonfiguration aus einer Datei lesen und entsprechende Veränderungen in der ProjectConfig-Instanz überschreiben.
Ich denke du solltest das "new Managers()" in den Konstruktor der ProjectConfig Klasse packen. Dann kannst du nämlich beim erzeugen der Projekt-Konfiguration die entsprechenden direkt mitgeben. Damit machst du dir auch Unittests viel einfacher.
> (Und zu dem Managers/Manager-Namen: Ich hab 3 verschiedene Manager-Typen
Warum hast du dann nicht 3 Klassen für die unterschiedlichen Manager-Typen?
> einer kümmert sich halt um das erzeugen der Instanzen der Plugins, einen der sich darum kümmert welche Klassen noch geladen sein sollten und einen der sich bei noch nicht geladenen Klassen darum kümmert, den entsprechenden ClassLoader zu beschaffen. Über die Konfiguration soll es dann halt möglich sein, verschiedene Manager zu benutzen, bei der "Standardvariante" können die Plugins zur Laufzeit nicht ersetzt werden, so dass man immer das ganze Programm neustarten müsste um zb. eine neue Version eines Plugins zu installieren, eine andere Variante der Manager merkt sich welche Instanz, eine Referenz auf andere Instanzen hat und somit wäre es möglich zur Laufzeit einfach nur diese Instanzen kurz "herunter zu fahren", die neue Plugin-Version einzuspielen und die neuen Plugins wieder zu starten.)
Wenn ich dich richtig verstehe, dann willst du wie gesagt 3 verschiedene Manager Klassen haben, wobei du von jeder Klasse eine Instanz beim Initialisieren der Projektkonfiguration übergibst. Später kann man dann in der Projektkonfiguration einfach ein "set"
> > > Nun hätte ich es gerne so, dass ich aus dieser Basis heraus 2 verschiedene Klassentypen hätte:
> > > Einmal nur lesbar und einmal les- und schreibbar.
> >
> > Was genau wird mit diesen Strings wie "ds.managers.ClassLoaderManager" passieren? Werden diese Klassen/Pakete irgendwie importiert oder so?
> Das geht glaube ich aus obigem hervor.
Für mich leider noch nicht so richtig. Könntest du vielleicht ein Code-Beispiel geben?
> > > Eine Variante wäre alle Member protected zu machen, ProjectConfig und Managers mit Getter-Funktionen auszustatten und daraus dann je eine Klasse mit Setter-Funktionen abzuleiten.
> > > Nun find ich das allerdings eine recht umständliche Lösung. Ich hätte es lieber so, dass ich nur eine schreib- und lesefähige "Hauptklasse" kreieren müsste und beliebig viele nur lesefähige Klassen bauen könnte.
> >
> > Also ich würde jetzt aus dem Bauch heraus eher vorschlagen, dass du ein Interface "ConfigReadable" erstellst, in dem du die nötigen getter definierst. Daneben würde ich dann ein weiteres Interface "ConfigWritable" erstellen, was "Configreadable" implementiert und um Methoden zum Ändern der Daten definiert. Aber sauber erscheint mir das auch nicht...
> >
> > > Ich könnte das ganze über ein Worterbuch a la List<String, Object> lösen, nachteil dabei ist aber, dass dann keine Vervollständigung per IDE möglich ist und im Endeffekt werden das um die 100 Schlüssel.
> > Wieso ist dann keine Vervollständigung möglich? Und warum das Object? Object sollte man möglichst vermeiden, wenn es nicht anders geht.
> Hier meinte ich die Autovervollständigung der IDEs. Bei `(new ProjectConfig()).getManagers().getInstanceManager()`{:.language-java} kann man halt die Autovervollständigung der IDEs verwenden. Bei einer Liste aber `(new CfgListe()).get("managers.instancemanager");`{:.language-java} würde das nicht mehr funktionieren.
Woher kommt jetzt CfgListe?
Naja du kannst auch mit
CfgListe meineconfig = new CfgListe(new InstanceManager(), new SonstwasManager(), ...);
meineconfig.getInstantManager();
Auf die Manager zugreifen mit Codevervollständigung. Voraussetzung ist, dass die unterschiedlichen Manager eigene Klassen sind, denn woher soll der Compiler sonst auch wissen, dass es 3 unterschiedliche Manager gibt?
> Was ich quasi suche ist etwas mit dem ich hinterher nur eine Klasse hab aus der heraus ich die Setter "deaktivieren" könnte a la:
> ~~~java
ProjectConfig cfg = new ReadOnly(new ProjectConfig());
> cfg.getOnwer();
> cfg.setOnwer("bla"); // wirft UnsupportedOperationException
> cfg.getManagers().setInstanceManager(); // wirft UnsupportedOperationException
> cfg.getManagers().getInstanceManager();
>
Ah, ich glaube langsam verstehe ich etwas besser.
Wenn du es mit den Interfaces machst wie beschrieben, dann hast du den großen großen Vorteil, dass du in deinem Codebeispiel schon zur Compilezeit eine Fehlermeldung kriegen würdest, weil der Compiler erkennen würde, dass die Instanz "cfg" das Interface "ReadableConfiguration" implementiert und daher gar keine "setInstanceManager()" Methode hat. Es würde also keine UnsupportedOperationException werfen, sondern schon in der IDE würde man sofort sehen, dass die setInstanceManager() Methode gar nicht aufgerufen werden kann, die getInstanceManager() Methode hingegen schon. Gleiches gilt natürlich für setOwner().
Also:
Mach ein Interface "ReadableProjectConfiguration", welches NUR die getXXX Methoden vorschreibt.
Mach danach ein Interface "WritableProjectConfiguration", welches ReadableProjectConfiguration implementiert und dann zusätzlich alle setXXX Methoden vorschreibt.
Ggf. kannst du auch gleich Klassen anstatt von Interfaces nehmen, das kommt drauf an.
Mach außerdem für die 3 Manager jeweils eine eigene Klasse und am besten zusätzlich noch ein "ProjectConfigurationManager" Interface (oder ähnlich), dass diese Manger alle implementieren. Wenn du dann erstmal eine Instanz von deiner Klasse "ProjectConfiguration" erzeugst, gibst du dieser Klasse die entsprechenden Instanzen der Manager gleich mit. Je nachdem ob du dann eine ReadableProjectConfiguration oder eine WritableProjectConfiguration wählst, lässt sich die Konfiguration dann ändern oder eben nicht.