Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
KapselungWie würdet ihr ein Service Layer erreichbar machen ...
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...
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.
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...
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
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.
"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?
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.
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);
}
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...
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.
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);
}
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?
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?
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.
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)
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!