bubble: Java - Klassenstruktur - Readable - ReadWritable

Hallo,

ich kämpfe seit einigen Wochen mit einer guten Lösung für folgendes Problem:

Voraus, ich lasse "Sichtbarkeitskram" ala public, protected, private außen vor, da ich nicht wieß wie ich es machen soll.

Angenommen ich habe 2 Klassen nach folgender Struktur:

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";  
}

Das ganze ist ja mehr oder weniger eine Baumstruktur.

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.

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.

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.

Einfach interfaces mit Getter- bzw. Setter-Funktionen und die Klasse implementiert beide kommt nicht in Frage, da ein simples "umcasten" möglich ist. (Über Reflexion geht es zwar generell, aber das sollte außen vor bleiben)

Wie würdet ihr so etwas lösen?

PS: Das ganze ist im Endeffekt die Konfiguration eines Plugin-Frameworks, dass ich mehr oder weniger zu Übungszwecken bastel. (Falls diese Information wichtig ist, möchte ich es erwähnt haben)

MfG
bubble

--
If "god" had intended us to drink beer, he would have given us stomachs. - David Daye
  1. Morgen!

    Das ganze ist ja mehr oder weniger eine Baumstruktur.

    Das ist jedenfalls falsch. Ein Baum als Datenstruktur in der Programmierung ist rekursiv definiert und deine beiden Klassen erfüllen diese Definition nicht.

    Der Rest deines Postings ist für mich leider auch widersprüchlich und nicht nachvollziehbar.

    Wie würdet ihr so etwas lösen?

    Dazu sind wesentlich mehr Informationen nötig. Was konkret bezweckst du? Vor allem: Wie möchtest du die Klassen ProjectConfig und Managers konkret verwenden können?

    PS: Das ganze ist im Endeffekt die Konfiguration eines Plugin-Frameworks, dass ich mehr oder weniger zu Übungszwecken bastel. (Falls diese Information wichtig ist, möchte ich es erwähnt haben)

    Nun, die Information ist schon mal nicht schlecht. Sie reicht aber nicht.

    Grüße
    Bernhard

    1. Das ganze ist ja mehr oder weniger eine Baumstruktur.
      Das ist jedenfalls falsch. Ein Baum als Datenstruktur in der Programmierung ist rekursiv definiert und deine beiden Klassen erfüllen diese Definition nicht.

      Damit meinte die Verschachtelung der Objekte.

      Der Rest deines Postings ist für mich leider auch widersprüchlich und nicht nachvollziehbar.

      Verständlich, dadurch, dass ich nich genau weiß wie es im Endeffekt aussehen muss quäl ich mich irgendwie mit der Beschreibung.

      Wie würdet ihr so etwas lösen?
      Dazu sind wesentlich mehr Informationen nötig. Was konkret bezweckst du? Vor allem: Wie möchtest du die Klassen ProjectConfig und Managers konkret verwenden können?

      Ich hoffe meine Antwort auf Whouzuos Post bringt ein wenig mehr Licht ins Dunkel.

      MfG
      bubble

      --
      If "god" had intended us to drink beer, he would have given us stomachs. - David Daye
  2. Hallo,

    ich kämpfe seit einigen Wochen mit einer guten Lösung für folgendes Problem:

    Voraus, ich lasse "Sichtbarkeitskram" ala public, protected, private außen vor, da ich nicht wieß wie ich es machen soll.

    Angenommen ich habe 2 Klassen nach folgender Struktur:

    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.  
      
    
    > Das ganze ist ja mehr oder weniger eine Baumstruktur.  
      
    Sehe das ähnlich wie Bernhard, sofern du nicht noch soetwas wie ds.foo.bar zusätzlich zu den ds.managers.sonstwas Einträgen hast, sieht es eher nach einer Liste aus. (Naja, andererseits kann man einen Baum mit einer Tiefe von 1 ggf. auch als Liste sehen...)  
      
    
    > 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?  
      
    
    > 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.  
      
    
    > Einfach interfaces mit Getter- bzw. Setter-Funktionen und die Klasse implementiert beide kommt nicht in Frage, da ein simples "umcasten" möglich ist. (Über Reflexion geht es zwar generell, aber das sollte außen vor bleiben)  
      
    Umcasten ist das allerletzte was man tun sollte und zwar dann, wenn man die Grenzen von Java gerät. Vielleicht braucht man ja gar keine Reflection, aber dafür solltest du genauer erklären, was du da tun willst.
    
    1. 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.  
      (Und zu dem Managers/Manager-Namen: Ich hab 3 verschiedene 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.)  
        
      
      > > Das ganze ist ja mehr oder weniger eine Baumstruktur.  
      >   
      > Sehe das ähnlich wie Bernhard, sofern du nicht noch soetwas wie ds.foo.bar zusätzlich zu den ds.managers.sonstwas Einträgen hast, sieht es eher nach einer Liste aus. (Naja, andererseits kann man einen Baum mit einer Tiefe von 1 ggf. auch als Liste sehen...)  
      >   
      > > 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.  
        
      
      > > 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.  
        
      
      > > Einfach interfaces mit Getter- bzw. Setter-Funktionen und die Klasse implementiert beide kommt nicht in Frage, da ein simples "umcasten" möglich ist. (Über Reflexion geht es zwar generell, aber das sollte außen vor bleiben)  
        
      
      > Umcasten ist das allerletzte was man tun sollte und zwar dann, wenn man die Grenzen von Java gerät. Vielleicht braucht man ja gar keine Reflection, aber dafür solltest du genauer erklären, was du da tun willst.  
        
      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();  
      
      

      MfG
      bubble

      --
      If "god" had intended us to drink beer, he would have given us stomachs. - David Daye
      1. 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.

        1. 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?  
            
          
          > 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"  
            
          
          > Für mich leider noch nicht so richtig. Könntest du vielleicht ein Code-Beispiel geben?  
            
          Ich merke, ich muss noch viel weiter ausholen als gedacht.  
            
          Es gibt für die Manager 3 Schnittstellen  
            
          IClassLoaderManager, IClassManager und IInstanceManager.  
            
          Nachdem die Konfiguration geladen ist. Wird das eigentliche System initialisiert.  
            
          Da habe ich eine Singleton-Klasse namens Registry, welche die unteranderem die die Manager-Instanzen erzeugt und dann griffbereit hält.  
            
          Grundlegend sieht die Initialisierung der Manager dann so aus:  
          ~~~java
          try {  
          	classLoaderManager = createClassLoaderManager(projectCfg.getManagers().getClassLoaderManager());  
          } catch (Throwable e) {  
          	// loggen dass konfigurierter Manager nicht geht  
          	classLoaderManager = new ClassLoaderManager(/* daten */);  
          }
          

          Für die anderen Manager sieht das ganze vom Prinzip her genauso aus.

          Aber das ganze ist eigentlich schon viel zu weit im dahinter stehendem System und hat mit dem eigentlichen Problem nicht mehr viel zu tun.

          Hier meinte ich die Autovervollständigung der IDEs. Bei (new ProjectConfig()).getManagers().getInstanceManager() kann man halt die Autovervollständigung der IDEs verwenden. Bei einer Liste aber (new CfgListe()).get("managers.instancemanager"); würde das nicht mehr funktionieren.
          Woher kommt jetzt CfgListe?

          CfgListe sollte hier irgendeine Klasse sein die das List-Interface implementiert (dabei wäre ich dann auch schon bei dem Problem dass ich List<Entry<String, Object>> benutzen müsste, oder Zahlen/Boolean auch als String im Speicher halten müsste)

          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().

          Das mit der Autovervollständigung bezug sich nur auf das List.get("cfg.managers.instancemanager") vs. ProjectConfig.getManagers().getInstanceManager(); da man sich das "cfg.managers.instancemanager" merken müsste.

          CfgListe meineconfig = new CfgListe(new InstanceManager(), new SonstwasManager(), ...);
          meineconfig.getInstantManager();

          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.

          Hier steckt wieder eine "flache" Struktur wie bei einer Liste dahinter, ich würde gerne eine geschachtelte Struktur beibehalten wollen.

          Für die Konfiguration der eigentlichen Instanzen der Plugins muss ich auf Listen zurückgreifen, das will ich übersogenannte Profile erreichen, diese sollen von einander erben können, angenommen die Projekt-Konfiguration ist als XML-Datei gespeichert, so hab ich folgende Struktur (Profile haben 1 bzw. 2 Eigenschaften, einen Dateinamen und optional noch ein Parent-Profil)

          <profile name="default.ini">  
          	<profile name="general_1.ini">  
          		<profile name="specificA.ini" />  
          		<profile name="specificB.ini" />  
          	</profile>  
          	<profile name="specificC.ini" />  
          </profile>
          

          Quasi würde in der ProjectConfig-Klasse noch ein weiterer Member stecken:

          class ProjectConfig {  
          	String owner = "unknown";  
          	Managers managers = new Managers();  
          	Profile profile = new Profile();  
          }  
            
          class Profile {  
          	String name = "default.ini";  
          	Profile parent = null;  
            
          	Profile getParent() {  
          		return parent;  
          	}  
          }
          

          Durch die Verschachtelung hab ich dann nicht einfach nur IConfigReadable, IConfigWriteable und dessen Implementation, sprich 4 Dateien, sondern Gruppierungsklassen (Also Profile, ProjectConfig, Managers, usw) mal 4 Dateien.

          Ich würde das ganze lieber so machen, dass ich eine Klasse schreibe, die beides Implementiert und dann eine allgemeine Wrapper-Klasse die das eigentliche Objekt readonly macht.

          So, dass ich nur noch Grupperungsklassen*3 + 1 (der Readonly-Wrapper) Dateien habe.

          MfG
          bubble

          --
          If "god" had intended us to drink beer, he would have given us stomachs. - David Daye
          1. So, dass ich nur noch Grupperungsklassen*3 + 1 (der Readonly-Wrapper) Dateien habe.

            Ich hab jetzt eine für mich akzeptable Lösung gefunden. Eher durch Zufall bin ich darauf gestoßen:

            public class ReadOnly implements InvocationHandler {  
            	public static Object get(Class<?> iface, Class<?> makeReadOnly, Object object) {  
            		return Proxy.newProxyInstance(iface.getClassLoader(), new Class[]{iface}, new ReadOnly(object, makeReadOnly));  
            	}  
            	private final Class<?> makeReadOnly;  
            	private final Object source;  
            	  
            	public ReadOnly(Object source, Class<?> makeReadOnly) {  
            		this.source = source;  
            		this.makeReadOnly = makeReadOnly;  
            	}  
              
            	@Override  
            	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
            		String methodName = method.getName();  
            		if(methodName.toLowerCase().startsWith("set")) {  
            			throw new UnsupportedOperationException();  
            		}  
            		else {  
            			Method sourceMethod = source.getClass().getMethod(methodName, method.getParameterTypes());  
            			Object result = sourceMethod.invoke(source, args);  
            			if(makeReadOnly.isAssignableFrom(result.getClass())) {  
            				Class<?> rcl = sourceMethod.getReturnType();  
            				result = ReadOnly.get(rcl, makeReadOnly, result);  
            			}  
            			return result;  
            		}  
            	}  
            }
            

            Das einzige was noch nicht wirklich passt, ich jetzt aber vernachlässige ist, dass man dann die set*-Funktionen trotzdem noch sieht:

              
            public interface IConfig {}  
              
            public interface IProjectConfig extends IConfig {  
            	public String getOwner();  
            	public void setOwner(String owner);  
            	public IManagers getManagers();  
            	public void setManagers(IManagers managers);  
            }  
              
            public interface IManagers extends IConfig {/* ... */}  
              
            public class ProjectConfig implements IProjectConfig {  
            	protected String owner;  
            	protected IManagers managers;  
            	public ProjectConfig() {/* ... */}  
            	public ProjectConfig(String owner, IManagers managers) {/* ... */}  
            	public String getOwner() {/* ... */}  
            	public void setOwner(String owner) {/* ... */}  
            	public IManagers getManagers() {/* ... */}  
            	public void setManagers(IManagers managers) {/* ... */}  
            }  
              
            public class Managers implements IManagers {/* ... */}
            

            Erzeugen kann ich das ganze dann ganz einfach mit:
            IProjectConfig cfgRO = (IProjectConfig) ReadOnly.get(IProjectConfig.class, IConfig.class, new ProjectConfig());

            Ob ich die set*-Funktionen noch irgendwie aus der IDE rausbekomme muss ich dann noch gucken.

            MfG
            bubble

            --
            If "god" had intended us to drink beer, he would have given us stomachs. - David Daye