DesignPattern: Übergabe von oft immergleichen Parametern an einen Konstruktor
-
Guten Tag,
viele meiner Klassen erfordern bei deren Instanziierung unabhängig von dem was sie tun immer ein oder zwei immergleiche Parameter: Jeweils eine Referenz auf einen Logger und auf eine Art Anwendungskonfiguration, die z.B. grundlegende Dinge wie das verwendete Maßsystem speichert.
Es ist mühsehlig die immer bei jeder Instanziierung angeben zu müssen. Gibt es eine elegantere Lösung? Globale Variablen für die Konfiguration und den Logger kommen nicht in Frage.
Meine beste Idee ist bis jetzt eine Art Factory-Klasse zu erstellen, die einmalig mit Referenzen auf Logger und Konfig ausgestattet wird und die mir dann die mühselige Objektkonstruktion in den Factory-Methoden abnimmt.
Allerdings ergeben sich hierraus dann andere Probleme. Ich würde gar nicht soviel sparen. Anstatt:Foo *pFoo = new Foo(&logger, &config);würde man dann
Foo *pFoo = pFactory->CreateFoo();schreiben. Man schleppt also anstatt 2 Referenzen nur noch eine umher und verbaut sich obendrein die Möglichkeit Objekte von Foo auf dem Stack anzulegen. Ausserdem würde die Factory-Klasse wird ziemlich aufgebläht (sie kennt alle Klassen die nichts miteinander zu tun haben, ausser dass sie die beiden Parameter erfordern). Aus diesen Gründen fällt die Factory-Idee eigentlich auch schon raus.
Andererseits will ich um einen Übergabeparamter zu sparen den "Logger" auch nicht in "Config" integrieren, denn es gibt mehrere Logfiles.Fällt jemandem von euch noch was schlaues ein, oder sollte ich in den sauren Apfel beissen und die beiden Parameter eben übergeben?
vielen Dank!
-
Evtl. wäre "Prototype" das richtige für dich. Das wäre eine etwas allgemeinere Version von deiner "Factory"-Idee.
-
TonyDinoso schrieb:
Andererseits will ich um einen Übergabeparamter zu sparen den "Logger" auch nicht in "Config" integrieren, denn es gibt mehrere Logfiles.
Wenn die Klassen selbst wissen welchen Logger sie brauchen, dann kannst du ja auch alle Logger mit in das Config Objekt reinpacken. Und die Klasse nimmt sich dann einfach denjenigen den sie verwenden mag.
Fällt jemandem von euch noch was schlaues ein, oder sollte ich in den sauren Apfel beissen und die beiden Parameter eben übergeben?
Ich würde vermutlich einfach die beiden Parameter übergeben.
Maximal könntest du noch gucken ob du die Sache mit dem Logger irgendwie vereinfachen kannst (threadlocal statics oder sowas).
-
Ich habe ein ähnliches "Phänomen", das passiert halt eben wenn man Dependency Injection statt Singletons o.ä. verwendet. Dennoch halte ich es für die bessere Lösung.
Factory ist oft so ein Monster-Pattern, das viel aufbläht. Das muss man gut rechtfertigen, sehe ich an dieser Stelle aber nicht ausreichend gerechtfertigt.
Wo genau siehst Du denn die Arbeit bei den Parameterübergaben? Das ist ja erstmal nicht viel Aufwand. Blöd ist nur, dass bei tiefen Verschachtelungen von Klassen, du immer etwas mitschleppen musst. Und vergisst Du es Mal, erhält man keinen eindeutigen Fehler, das wundert einen dann jedes Mal wieder, bis man merkt, dass man wieder die Übergabe vergessen hat.
Du könntest höchstens aus beiden Parametern einen machen, indem Du eine Art Initializer-struct erstellst. Wenn Dir später dann auffällt, dass Du etwas Drittes derart benötigst, könntest Du es dann einfach dazupacken. Nachteil ist wieder etwas mehr Gewusel, wenn Du den Logger dann nutzen wollen würdest.
Also alles in allem würde ich es einfach übergeben, mir fällt keine bessere Lösung ein.

-
TonyDinoso schrieb:
Foo *pFoo = new Foo(&logger, &config);Unter der Annahme, dass alle deine Klassen von einer Basis-Klasse "LoggerConfig" abgeleitet sind...
Könnte man den operator() überladen.
Das könnte dann (absolut ungetestet grade) etwa so aussehen:Foo *pFoo = new Foo()(&logger, &config);Alternativ könnte man auch via CRTP was zaubern, ohne mich zu weit aus dem Fenster zu lehnen
und wieder absolut ungetestet// Hier passiert dann implizite Konvertierung Foo *pFoo = new magic<Foo, &logger, &config>() // Die eigentliche Template-Klasse ist irrelevant.
-
Wenns nur un Mitarbeit geht...
#define CREATE_A new A (b, c)
-
Oder gleich
#define LOCO ,&logger,&config
-
...
-
Ich falle immer mehr der Idee anheim, dass man ab einem gewissen Softwareumfang mit gegebener Strukturierung und Modularisierung entweder genannte Tricks anwenden kann und mit der Zeit immer ekligerer Code mit Templates und Makros entsteht, oder aber vielleicht besser damit fährt, sich Wizards und Snippets für die Entwicklungsumgebung der Wahl zu programmieren. Letzteres wollte ich in nächster Zeit mal angehen. Aber ich bin nun auch an einem Projekt am werkeln, bei dem man davon wohl schon "by design" am meisten hat, bei "euren" Projekten mag das anders aussehen.
Edit: Vielleicht um den Kontext mal überhaupt zu erwähnen. Ich habe an mir das Syndrom festgestellt, dass ich nach gegebener klarer Schnittstellendefinition viel Mühe in abstruseste Template-Basisklassen-Konstrukte usw. gesteckt habe, die zwar alles, was ich zu dem Zeitpunkt gemacht habe zu Einzeilern werden lässt und erst einmal das große ganze klarer machten, aber ein Jahr später weiß ich überhaupt gar nicht mehr, warum dort wo und warum irgendwelche Limitationen sind, die die Schnittstellendefinition so erstmal gar nicht nahelegt. Ich nenne es liebevoll das "Basisklassenfriemelsyndrom".
-
LOCO?
Für nurfs Vorschläge könnte ich BAKA (BAsisKlasse für Argumente) als Name anbieten.
(EDIT: Nix gegen dich, nurf, passt nur grad so schön ;))
-
...