Kapselung Wie würdet ihr ein Service Layer erreichbar machen ...

X5-599

Top Contributor
Puh, Glück gehabt. Hört sich so an als wäre ich auf dem richtigen (zumindest nicht ganz verkehrten) Weg. Und nein, es läuft nicht im EE etc Kontext. Im Grunde ist es ja mein Ziel einmal auf CI-Container zu wechseln. Aber zuerst muss die Anwendung stabil laufen. Dann habe ich genug Zeit mich damit zu beschäftigen und kann auch mehr oder weniger dafür geradestehen...

Nochmal zu dem "statischen". Ich denke du verstehst, dass ich das ja nur mache damit ich die Factory mit samt dem "teuren" SessionFactory Objekt nur einmal bauen muss und immer Zugriff drauf habe. Wie würdest du das denn "nicht statisch" machen? Mir fällt da nur der Weg ein wie ich ihn als erstes Code Beispiel aus Post #49 beschrieben habe...
 

mrBrown

Super-Moderator
Mitarbeiter
Nochmal zu dem "statischen". Ich denke du verstehst, dass ich das ja nur mache damit ich die Factory mit samt dem "teuren" SessionFactory Objekt nur einmal bauen muss und immer Zugriff drauf habe. Wie würdest du das denn "nicht statisch" machen? Mir fällt da nur der Weg ein wie ich ihn als erstes Code Beispiel aus Post #49 beschrieben habe...
Man könnte die Instanz zB in einer lokalen Variable halten (zB der main) oder als Instanzvariable in einem Objekt, was es nur einmal gibt. Je nach Kontext sind die mehr oder weniger gut geeignet.

Von überall Zugriff braucht man auf diese Factory ja nicht, man will ja nicht erreichen, dass alle eine SessionFactory bekommen können, sondern erstmal nur, dass die Services da verfügbar sind, wo man sie benötigt.
Das man dafür ein DAO und für das DAO eine SessionFactory braucht, ist in dem Fall ja Implementierungsdetail.
Wenn man dass dann geschickt löst (ohne Container schnell schwierig), kennt nur eine einzige Methode diesen Aufbau, und alle anderen bekommen einfach das, was sie brauchen, ob das jetzt ServiceA, Dao oder XY ist.
 

X5-599

Top Contributor
Man könnte die Instanz zB in einer lokalen Variable halten (zB der main) oder als Instanzvariable in einem Objekt, was es nur einmal gibt.

Und genau da komme ich nicht mehr mit. Wenn ich die Instanz lokal in der main halte, komme ich ja auch nur "beim Start" der Anwendung da ran. Also könnte ich alle davon Abhängigen Objekte auch nur zum Startzeitpunkt erzeugen.

Von überall Zugriff braucht man auf diese Factory ja nicht, man will ja nicht erreichen, dass alle eine SessionFactory bekommen können, sondern erstmal nur, dass die Services da verfügbar sind, wo man sie benötigt.
Das man dafür ein DAO und für das DAO eine SessionFactory braucht, ist in dem Fall ja Implementierungsdetail.
Wenn man dass dann geschickt löst (ohne Container schnell schwierig), kennt nur eine einzige Methode diesen Aufbau, und alle anderen bekommen einfach das, was sie brauchen, ob das jetzt ServiceA, Dao oder XY ist.

Überall direkten Zugriff nicht. Stimmt. Aber wenn ich doch von irgendwo in meiner Anwendung einen neuen z.B. Controller erzeugen will und dem die nötigen Services übergeben will, dann brauche ich nunmal die DAOs um diese Services erzeugen zu können. Und wenn Hibernate verwendet wird, dann brauch ich auch das SessionFactory Objekt. Wenn das dann lokal in der main liegt, komme ich nicht mehr heran.

Mache ich mich ein wenig verständlich? Es scheint als habe ich noch kein Verständnis dafür wie ich dieses Konzept in eine Anwendung einbaue, die aus mehr als nur er main Methode besteht, die nur einen Controller/Service/Dao erzeugt...
 

mrBrown

Super-Moderator
Mitarbeiter
Und genau da komme ich nicht mehr mit. Wenn ich die Instanz lokal in der main halte, komme ich ja auch nur "beim Start" der Anwendung da ran. Also könnte ich alle davon Abhängigen Objekte auch nur zum Startzeitpunkt erzeugen.

Überall direkten Zugriff nicht. Stimmt. Aber wenn ich doch von irgendwo in meiner Anwendung einen neuen z.B. Controller erzeugen will und dem die nötigen Services übergeben will, dann brauche ich nunmal die DAOs um diese Services erzeugen zu können. Und wenn Hibernate verwendet wird, dann brauch ich auch das SessionFactory Objekt. Wenn das dann lokal in der main liegt, komme ich nicht mehr heran.

Mache ich mich ein wenig verständlich? Es scheint als habe ich noch kein Verständnis dafür wie ich dieses Konzept in eine Anwendung einbaue, die aus mehr als nur er main Methode besteht, die nur einen Controller/Service/Dao erzeugt...
In vielen Fällen klappt das, entweder mit Objekten oder mit Factorys, die man weiter gibt - aber natürlich gibt es auch immer Fälle, in denen es nicht klappt.

Als kleines Beispiel, ein Controller A (mit Service A, Dao A) wird zum Start der Anwendung gebraucht, und dieser soll irgendwann einmal Ein Fenster mit Controller B (mit Service B, Dao B) anzeigen.

Controller A wird dann in der Main initialisiert mit Service A und Factory B für Controller B
Service A wird direkt mit Dao A gefüllt, Factory B entweder mit Service B, oder einer Factory für Service B.


Mit steigender Menge an Abhängigkeiten wird's natürlich unpraktischer, deshalb greift man meist schnell zu DI-Controllern (die intern quasi das gleiche machen.) Aber auch damit muss man es ähnlich lösen, wenn man in den Klassen eine harte Abhängigkeit zum Container vermeiden will
 
Verstanden, was Forward Declaration damit zu tun haben soll, hab ich allerdings nicht. Genausowenig, warum das Einfluss auf DI hat.

Tja. Das ist halt der Unterschied. Ich versteh dich, obwohl du eine mir fremde Terminologie verwendest.

im Übrigen ist es Quatsch meine Implementeriung mit einem Compositum zu vergleichen, weil a) keine 1:N beziehung besteht und b) die verantwortlichkeitskette richtung parent geht und nicht richtung child, wie bei dem bekannten GOF-Pattern.

Ich weiss zwar, was Du gemeint hast, aber ich reite trotzdem drauf rum.
 

mrBrown

Super-Moderator
Mitarbeiter
Tja. Das ist halt der Unterschied. Ich versteh dich, obwohl du eine mir fremde Terminologie verwendest.
"Forward Declaration" ist mir keineswegs fremd, ich seh nur absolut keinen Zusammenhang zwischen Forward Declaration und DI. Und erst recht nicht, warum Forward Declaration eine Voraussetzung für DI sein soll.
(Oder meinst du mit Forward Declaration wieder etwas anderes als die übliche Bedeutung?)

im Übrigen ist es Quatsch meine Implementeriung mit einem Compositum zu vergleichen, weil a) keine 1:N beziehung besteht und b) die verantwortlichkeitskette richtung parent geht und nicht richtung child, wie bei dem bekannten GOF-Pattern.

Ich weiss zwar, was Du gemeint hast, aber ich reite trotzdem drauf rum.

Du hast es als Baum beschrieben, ein Baum ist üblicherweise 1:n.

Aber ja, Kompositum war eine etwas überstürzte Einschätzung, Chain of Responsibility beschreibt es vermutlich besser, oder hast du dich eher an einem anderem Pattern orientiert?
 

X5-599

Top Contributor
Als kleines Beispiel, ein Controller A (mit Service A, Dao A) wird zum Start der Anwendung gebraucht, und dieser soll irgendwann einmal Ein Fenster mit Controller B (mit Service B, Dao B) anzeigen.

Genau an so etwas hatte ich gedacht :)

Controller A wird dann in der Main initialisiert mit Service A und Factory B für Controller B
Service A wird direkt mit Dao A gefüllt, Factory B entweder mit Service B, oder einer Factory für Service B.

Also anstatt in Controller A (an der Stelle wo der neue Controller gebaut wird) mit meiner bisherigen DaoFactory das nötige Dao zu erzeugen, das dann in den entsprechenden Service zu packen und diesen Service dann dem Controller B mitzugeben, würdest du eine spezialisierte Factory aufrufen die dir dann den Service für B liefert?
Und diese spezialisierte Factory ist ein Objekt, dass du dem Controller A mitgegeben hast?

Das hieße, jeder weitere Controller hätte als Konstruktor Parameter jeweils die Factories (für Services) die er braucht um diese Abhängigkeiten für weitere Controller zu erzeugen? Und natürlich zusätzlich einen Parameter des selbst zu nutzenden Services.

Erweitertes Beispiel: Controller A -> Controller B -> Controller C

Code:
main()
{
  SessionFactory sessionFactory = new Configuration(...) ...;
  
  DaoA daoA = new HibernateDaoImpl(sessionFactory);
  ServiceA serviceA = new ServiceAImpl(daoA);

  ServiceFactoryB factoryB = new HibernateServiceFactoryB(sessionFactory);
  ServiceFactoryC factoryC = new HibernateServiceFactoryC(sessionFactory);

  ControllerA controllerA = new ControllerA(serviceA, factoryB, factoryC);
}

Code:
//In ControllerA
public ControllerA(SerivceA serviceA, ServiceFactoryB factoryB, SeviceFactoryC factoryC)
{
}

private void createControllerB()
{
  ServiceB serviceB = factoryB.getServiceB();
  
  ControllerB controllerB = new ControllerB(serviceB, factoryC);
}

Code:
//In ControllerB
public ControllerB(SerivceB serviceB, ServiceFactoryC factoryC)
{
}

private void createControllerC()
{
  ServiceC serviceC = factoryC.getServiceC();
  
  ControllerC controllerC = new ControllerC(serviceC);
}


Mit steigender Menge an Abhängigkeiten wird's natürlich unpraktischer, deshalb greift man meist schnell zu DI-Controllern (die intern quasi das gleiche machen.) Aber auch damit muss man es ähnlich lösen, wenn man in den Klassen eine harte Abhängigkeit zum Container vermeiden will

Da hast du Recht. Je größer die Anwendung desto mehr Controller/Abhängigkeiten und somit längere Parameter Listen. Da fiele mir nur ein das Design so anzulegen, dass zB nicht A -> B -> C gilt sondern: A -> B, und A -> C.
Das einzige was immer bliebe ist: Der erste Controller braucht alle der Anwendung bekannten Service Factories...

Oder eben man nutzt die bekannten DI-Frameworks :)
 

mrBrown

Super-Moderator
Mitarbeiter
Also anstatt in Controller A (an der Stelle wo der neue Controller gebaut wird) mit meiner bisherigen DaoFactory das nötige Dao zu erzeugen, das dann in den entsprechenden Service zu packen und diesen Service dann dem Controller B mitzugeben, würdest du eine spezialisierte Factory aufrufen die dir dann den Service für B liefert?
Und diese spezialisierte Factory ist ein Objekt, dass du dem Controller A mitgegeben hast?
Ja, nur würde ich keine Factory für Service B mitgeben, sondern eine Factory für Controller B.

Das hieße, jeder weitere Controller hätte als Konstruktor Parameter jeweils die Factories (für Services) die er braucht um diese Abhängigkeiten für weitere Controller zu erzeugen? Und natürlich zusätzlich einen Parameter des selbst zu nutzenden Services.
Jein, jeder Controller natürlich erstmal alle Services die er selber braucht. Alle anderen Services muss er gar nicht kennen, auch nicht über Factorys. Statt Factorys für Services würde ich mit Factorys für Controllern arbeiten.

Controller A soll irgendwann mal Controller B erstellen -> also bekommt Controller A die Möglichkeit mitgegeben, Controller B zu erstellen.

Um dein Beispiel einmal entsprechend anzupassen:

Code:
main()
{
  SessionFactory sessionFactory = new Configuration(...) ...;
 
  DaoA daoA = new HibernateDaoImpl(sessionFactory);
  ServiceA serviceA = new ServiceAImpl(daoA);

  ServiceFactoryB factoryB = new HibernateServiceFactoryB(sessionFactory);
  ServiceFactoryC factoryC = new HibernateServiceFactoryC(sessionFactory);
  
  ControllerCFactory controllerCFactory = () -> new ControllerC(factoryC.getService())
  ControllerBFactory controllerBFactory = () -> new ControllerB(factoryB.getService(),controllerCFactory)

  ControllerA controllerA = new ControllerA(serviceA, controllerBFactory);
}

Code:
//In ControllerA
public ControllerA(SerivceA serviceA, ControllerBFactory controllerBFactory)
{
}

private void createControllerB()
{
   ControllerB controllerB = controllerBFactory.get();
}

Code:
//In ControllerB
public ControllerB(SerivceB serviceB, ControllerCFactory controllerCFactory)
{
}

private void createControllerC()
{ 
  ControllerC controllerC = controllerCFactory.get();
}

(Bin grad unterwegs, uU sind kleinere Typos drin...)
 

X5-599

Top Contributor
Ah, wir kommen der Sache näher.

Heißt diese Zeile:
Code:
ControllerCFactory controllerCFactory = () -> new ControllerC(factoryC.getService())
soviel wie:
Code:
ControllerCFactory controllerCFactory = new ControllerCFactory(factoryC)

//und in ControllerCFactory:
public ControllerC get()
{
  return new ControllerC(factoryC.getService())
}

Und: Es heißt zwar hier "factoryC.getService()" aber in Wirklichkeit wird doch bestimmt bei jedem Aufruf von der factoryC ein neues Service Objekt erzeugt, oder?
 

mrBrown

Super-Moderator
Mitarbeiter
Heißt diese Zeile:
soviel wie:
Ja ;)

Und: Es heißt zwar hier "factoryC.getService()" aber in Wirklichkeit wird doch bestimmt bei jedem Aufruf von der factoryC ein neues Service Objekt erzeugt, oder?
Kommt drauf an, die FactoryC könnte das bei Services durchaus cachen und immer das gleiche ausliefern (und ist ja bei Services auch angebracht).

Alternativ könnte man natürlich auch schon direkt den Service setzen, und für den keine Factory nutzen, dann ist's halt nicht mehr Lazy
 

X5-599

Top Contributor

Yay.


Kommt drauf an, die FactoryC könnte das bei Services durchaus cachen und immer das gleiche ausliefern (und ist ja bei Services auch angebracht).

Verstehe. Wäre dieses einmalige Erzeugen und cachen auch bei den ControllerFactories angebracht?

Alternativ könnte man natürlich auch schon direkt den Service setzen, und für den keine Factory nutzen, dann ist's halt nicht mehr Lazy

Der Gedanke ist mir auch gekommen. Aber ich denke das Lazy Loading ist schon nicht verkehrt. Wird dann ja nur wirklich das erzeugt was auch benötigt wird und nicht alles auf einmal.
 

mrBrown

Super-Moderator
Mitarbeiter
Verstehe. Wäre dieses einmalige Erzeugen und cachen auch bei den ControllerFactories angebracht?
Kommt immer drauf an, wenn man die cached, müssen sie in jedem Fall stateless sein, das kann bei GUIs schwierig bis unmöglich werden (wenn man zB ein Fenster zwei mal anzeigen will, braucht jedes einen eigenen Controller)
 

X5-599

Top Contributor
Schön. Ergibt Sinn für mich. Danke für die Erklärung. Ich denke ich habe nun genug Informationen um ein recht ansehnliches Projekt zu realisieren. Heißen Dank an dich @mrBrown und auch an alle anderen die zu diesem Thread begetragen haben. Ihr seid super!
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
nrg Wie würdet ihr eine "Dauerschnittstelle" implementieren? Allgemeine Java-Themen 5
M Wie würdet ihr Dokumente aus Java realisieren? Allgemeine Java-Themen 4
B Was würdet ihr dafür berechnen? Allgemeine Java-Themen 7
G Welches Java GUI Buch würdet Ihr empfehlen Allgemeine Java-Themen 2
J Wie würdet Ihr Daten 1 Jahres abbilden Allgemeine Java-Themen 2
izoards JAR als Windows Service mit Appache Procrun (prunsrv) Allgemeine Java-Themen 6
A Zweite Service Klasse beim Kompilieren Allgemeine Java-Themen 6
O Service oder Controller Allgemeine Java-Themen 6
OnDemand Thread / Service abbrechen Allgemeine Java-Themen 3
H Aufruf eines Web Service anhand übergebenen Parameter Allgemeine Java-Themen 2
K Multithreading: Service(Task), wait und continue Allgemeine Java-Themen 21
X Threads Java Chached Executors Service Allgemeine Java-Themen 12
P Entity Objekt Methoden vs Service methoden Allgemeine Java-Themen 2
K Hilfe bei GUI für Pizza-Service Allgemeine Java-Themen 11
L TV Programm API/Web Service o.ä. Allgemeine Java-Themen 6
D Java Objekt als Service in Runtime registrieren Allgemeine Java-Themen 1
Nero90 FileSystem Watcher Service Allgemeine Java-Themen 1
W Windows (Service) Hooking Allgemeine Java-Themen 8
C Threads ExecutorService shutdown abbrechen und service "starten" ? Allgemeine Java-Themen 3
A Framework für einen Web Service Allgemeine Java-Themen 6
M Webservices: WSDL Files ohne "Service" Element? Allgemeine Java-Themen 4
D ewig laufendes Javaprogramm ("Service") Allgemeine Java-Themen 17
D Executor Service nach getaner Arbeit beenden Allgemeine Java-Themen 3
Iron Monkey Listening for Print Service Status Changes Allgemeine Java-Themen 2
D Daemon bzw. Windows Service Allgemeine Java-Themen 5
O Unterschied zwischen ThreadPoolExecutor und Executor Service Allgemeine Java-Themen 7
J url-Service timeout einrichten? Allgemeine Java-Themen 10
G Java App als Service Allgemeine Java-Themen 2
N C source to Java Source -> compile java layer? Allgemeine Java-Themen 9
K layer in Jsp Aktualisieren Allgemeine Java-Themen 3

Ähnliche Java Themen


Oben