Ein Objekt einer Klasse mehreren anderen Klassen zur Verfügung stellen?

berndoa

Top Contributor
Hallo,
ich habe in meinem Java Projekt aktuell folgende Klassenstruktur:
1.png
Details sind im IPrinzip egal, Punkt ist, es gibt sowas wie eine "Wurzelklasse".
Also eine Klasse, von der in der einzigen Main Methode ein Objekt erzeugt wird.
Deren Attribute/"Felder" haben Referenzen auf Objekte von Klassen der "2. Stufe". usw.

Wie im Bild referenziert die oberste (linkeste) Klasse die Wurzel, deren Feldreferenzen zeigen auf Objekte dreier weiterr Klassen.
In jenen Klassenobjekten haben die dortigen Felder wieder Referenzen auf weitere Klassen, usw.
Übrigens gibt es von jeder Klasse nur genau ein Objekt, mehr nicht.
Ist also gewissermassen auch ein Klassenobjekt, wo man sieht welches Objekt welches referenziert.

Nun stehe ich vor dem Grundsätzlichen Problem, das ich die im Bild separat aufgelistete Klasse habe (die die mit Pfeil verbundene Klasse als innere Klasse hat).
Und im großen Baumgebilde oben vereinzelte Klassen Zugriff auf das selbe Objekt dieser bestimmten Klasse haben sollen.

Die lose Klasse liest eine Exceltabelle ein und macht vieles mehr, daher soll nur genau ein Objekt davon erzeugt werden auf das, wer befugt ist, Zugriff haben soll.

Ursprünglich dachte ich, sagen wir mal die Klassen mit Zugriff wären 1,4 und 5 und die sollen zugriff auf ein Objekt der Klasse A haben.

aktuell lasse ich die Wurzel ein Objekt der A Klasse erzeugen und reiche dies geiwssermassen immer weiter nahc unten bis zu den Klassen 1,4 und 5 durch.
Problem halt: Jede Klasse auf dem Weg dahin muss auch erst diese Referenz in Form eines Feldes speichern und dies dann ihrer nächstniedrigeren Klasse übergeben.

Ist keine wirklich schöne Lösung, aber ich hoffe sie funktioniert.
Konnte es, da noch nicht Alles fertig ist, noch nicht ausprobieren.

ist auch mehr so eine "quick and Dirty" Lösung.

Gibt es eine professionelle Möglichkeit, sowas zu lösen?
 
Mittlerweile ist meine Meinung zur Modellierung von Abhängigkeiten: Mache Abhängigkeiten immer explizit! Also, wenn eine Klasse A in einer ihrer Methoden eine Abhängigkeit auf ein Objekt einer Klasse B hat, dann sollte B ein Konstruktorparameter von A sein.
Die Orchestrierung, also, wer nun tatsächlich die Objekte erzeugt und miteinander "verkabelt" (also die Konstruktoren aufruft) kannst du im Prinzip manuell machen oder hierfür einfach ein Dependency Injection / Container Framework wie Google Guice oder Spring nehmen.
Auf keinen Fall sollte man aber Abhängigkeiten irgendwie "implizit" modellieren durch z.B. irgendwelche public static Variablen, auf die jeder und alles einfach so zugreifen kann.
Also ja: Wenn die Klasse ganz rechts auf dieses geteilte Objekt zugreifen muss, dann musst du es bei der Erzeugung irgendwie vom Anfang bis zu der Klasse ganz rechts durchschleifen.
Im Prinzip machst du dadurch auch ungünstige Modellierungen "sichtbar". Wenn es ein Pain ist, die Abhängigkeiten zu verwalten/durchzuschleifen, dann ist die objektorientierte Modellierung eventuell schlecht.
 
Mittlerweile ist meine Meinung zur Modellierung von Abhängigkeiten: Mache Abhängigkeiten immer explizit! Also, wenn eine Klasse A in einer ihrer Methoden eine Abhängigkeit auf ein Objekt einer Klasse B hat, dann sollte B ein Konstruktorparameter von A sein.
Die Orchestrierung, also, wer nun tatsächlich die Objekte erzeugt und miteinander "verkabelt" (also die Konstruktoren aufruft) kannst du im Prinzip manuell machen oder hierfür einfach ein Dependency Injection / Container Framework wie Google Guice oder Spring nehmen.
Auf keinen Fall sollte man aber Abhängigkeiten irgendwie "implizit" modellieren durch z.B. irgendwelche public static Variablen, auf die jeder und alles einfach so zugreifen kann.
Also ja: Wenn die Klasse ganz rechts auf dieses geteilte Objekt zugreifen muss, dann musst du es bei der Erzeugung irgendwie vom Anfang bis zu der Klasse ganz rechts durchschleifen.
Im Prinzip machst du dadurch auch ungünstige Modellierungen "sichtbar". Wenn es ein Pain ist, die Abhängigkeiten zu verwalten/durchzuschleifen, dann ist die objektorientierte Modellierung eventuell schlecht.
Naja, sagen wir es mal so:
Der Wurzelknoten sei die Klasse A.
Die davon ausgehenden Klassen seien AA,AB,AC,AD.
die von AA ausgehenden seien AAA,AAB,AAC.
die von AB ausgehenden AAA,AAB,AAC.
usw.

halt jetzt einfahc mal durchnummeriert je nach ebene.

Sagen wir die Klasse ABC benötige ein Objekt der Utility Klasse U.
Dann sieht aktuell A bei mir so aus:
Java:
public class A{
    AA aa=new AA();
AB ab=new AB();
AC ac=new AC();
U u=new U();

public A(){

ab.u=this.u;


}

}

Die Klasse AB hat dann ebenso ein eingangs auf null gesetztes U Feld, das wie oben gezeigt gesetzt wird.
Am Ende vom lied kennen dann a und ab das selbe Objekt u.

Genauso erzeugt ab die damit verbundenen Klassenobjekte aba,abb,abc.
und setzt in seinem Konstruktor
Code:
abc.u=this.u;

Wobei mir gerade klar wird dass das vermutlich scheitert weil der eine Konstruktor noch nicht fertig ist während der andere schon gesetzt werden soll. oder so.


das objekt von oben nahc unten als konstruktorparameter immer weiter zu reichen wäre auch eine Option, ggbfls.

Bin mi noch unklar wie man es am Besten macht ohne dass es probleme gibt


Vermutlich könnte man Alles ganz viel anders machen, aber so meine "Objekthierarchie" im Sinne obigen Baumes will ich schon beibehalten.
Weil ich dann in der A klasse dann bspw. eine Methode malen haben kann, die bestimmte Methoden der dmait verbundenen Objekte aufruft.

So im Sinne von einem Big Boss, der eine Aufgabe zu erledigen hat und diese nahc unten an die besser qualifizierten Spezialisten weiterreicht.
Und wenn bspw. der Ingeniuer den Befehl "bau ein Auto" kriegt, weiß er dann genau dass er vom Werkzeughersteller die Klasse "liefereWerkzeug() aufrufen muss, dann vom wem anders dessen spezielle methode, etc.

von oben nach unten ruft also eine allgemein methode immer speziellere Methoden der speziellisierteren unterklassen auf.

So irgendwie.

Dann weiß eine spezielle klasse bspw. genau wie es eine Farbe vom bildschirm einliest.
Die nächsthöhere Klasse. die den befehl "gib mir die bildschirmfarbe bei x,y" runtergegeben hat, muss aber nicht wissen wies geht, die untekrlasse ist da spezialisiert genug um auf anhieb zu wissen was es mit dem befehl machen muss und wie er umzusetzen ist.


Halt das zerlegung von großen aufgaben in mehrere kleinere über eine klassenhierarchie umgesetzt.
 
Abhängigkeiten einer Klasse sollten nicht einfach von außen als Feld auf ihr gesetzt werden, sondern einzig und alleine über den Konstruktor als Konstruktorparameter übergeben werden.
Was du machst, also die Klasse A einfach in die Klasse AB "hineingreifen" lassen und in ihr ein Feld setzen, ist schonmal ein Anti-Pattern.
Natürlich bekommst du hierdurch zusammen mit der implizitien Feldinitialisierung Probleme in der Reihenfolge.

Also: Nutze einzig und alleine Konstruktorparameter, um Abhängigkeiten von A nach AB zu transportieren. Kein Setzen von Feldern durch Klassen hinweg (also in deinem Fall von AB.u via A).

In dem Fall kannst du dann natürlich nicht einfach implizite Feldinitialisierungen benutzen, sondern deine Klasse A würde wie folgt aussehen:

Java:
public class A {
  private final AA aa;
  private final AB ab;
  private final AC ac;
  private final U u;
 
  public A() {
    u = new U();
    aa = new AA();
    ab = new AB(u);
    ac = new AC();
  }
}

Und AB seinerseits nutzt den Konstruktorparameter u, um seinerseits Instanzen zu erzeugen und u weiterzugeben (wo erforderlich).
 
Zuletzt bearbeitet:
Abhängigkeiten einer Klasse sollten nicht einfach von außen als Feld auf ihr gesetzt werden, sondern einzig und alleine über den Konstruktor als Konstruktorparameter übergeben werden.
Was du machst, also die Klasse A einfach in die Klasse AB "hineingreifen" lassen und in ihr ein Feld setzen, ist schonmal ein Anti-Pattern.
Natürlich bekommst du hierdurch zusammen mit der implizitien Feldinitialisierung Probleme in der Reihenfolge.

Also: Nutze einzig und alleine Konstruktorparameter, um Abhängigkeiten von A nach AB zu transportieren. Kein Setzen von Feldern durch Klassen hinweg (also in deinem Fall von AB.u via A).

In dem Fall kannst du dann natürlich nicht einfach implizite Feldinitialisierungen benutzen, sondern deine Klasse A würde wie folgt aussehen:

Java:
public class A {
  private final AA aa;
  private final AB ab;
  private final AC ac;
  private final U u;
 
  public A() {
    u = new U();
    aa = new AA();
    ab = new AB(u);
    ac = new AC();
  }
}

Und AB seinerseits nutzt den Konstruktorparameter u, um seinerseits Instanzen zu erzeugen und u weiterzugeben (wo erforderlich).
Das hieße, AB sähe dann in etwa so aus?
Java:
public class AB{
    private final ABC abc;
    public AB(U u){
        abc=new ABC(u);
    }
    
}

Kann ich das so einfach "durchreichen" ohne dass AB selbst auch als Feld die u referenz abspeichert?

Was ich mir auch nie sicher bin:
Sagen wir AB hat den Code wie oben.
Wenn nun in A (oder anderswo) ein neues Objekt der Klasse AB erzeugt wird,
werden dann erst die Felder des Objekts erzeugt (sowie die Methoden hinterlegt) und dann erst der ganze Kram im Konstruktor gemacht?
Wiel muss ja eigentlich, sosnt macht es nicht viel Sinn.
 
Das hieße, AB sähe dann in etwa so aus?
Java:
public class AB{
    private final ABC abc;
    public AB(U u){
        abc=new ABC(u);
    }
}
Korrekt.
Kann ich das so einfach "durchreichen" ohne dass AB selbst auch als Feld die u referenz abspeichert?
Wenn die Klasse AB selbst kein U braucht innerhalb seiner eigenen Methoden, klar. Dann kannst du das einfach durchreichen an ABC. Warum solltest du dann U als Feld innerhalb von AB selbst speichern?
 
Das hieße, AB sähe dann in etwa so aus?
Java:
public class AB{
private final ABC abc;
public AB(U u){
abc=new ABC(u);
}

}
Kann ich das so einfach "durchreichen" ohne dass AB selbst auch als Feld die u referenz abspeichert?
Ich würde sagen eher so:
Java:
public class AB{
    private final ABC abc;
  
    public AB(ABC abc){
        this.abc = abc;
    }
  
}
Wenn ABC eine Abhängigkeit von U hat, dann wird diese bei der Erzeugung von ABC angegeben. AB muss davon nichts wissen. Falls ein Zugriff auf das U von ABC notwendig ist, dann kann ABC einen getter dafür bereit stellen.
 

Neue Themen


Zurück
Oben