Hallo MB,
ich habe mir das jetzt fünfmal durchgelesen, aber es kommt mir doch arg verknotet vor, was Du da schreibst. Das meiste verstehe ich nicht.
Abstraktion ist kein Selbstzweck, man muss schon etwas dadurch gewinnen. Da Du nur symbolischen Code zeigst, ist der Nutzen schwer zu erkennen und ich muss Dir einfach glauben, dass du ihn hast.
Ich nehme an, dass deine ConcreteConstruct Klassen SQL Fragmente konstruieren. Vermutlich gibt's einen QueryConstruct, SelectConstruct, ein FromConstruct, ein TableReferenceConstruct, und vieles mehr. Diese Klassen solltest Du aber nicht zu sehr abstrahieren. Ein QueryConstruct braucht mehrere Abteilungen: Select, From, Where, GroupBy, Having und OrderBy. Ein Select besteht aus dem Keyword SELECT und einer Column-Liste. Im Falle von MS SQL Server auch noch aus einer TOP Klausel (welche bei MYSQL LIMIT heißt und nicht Teil der SELECT Klausel ist!). Eine Column-Liste besteht aus mehreren Column-Angaben, eine Column-Angabe besteht aus Inhalt und Alias, der Inhalt ist ein Spaltenname, eine Konstante oder eine Expression, etc etc.
All das bildet einen Baum (Syntax-Tree) und ein Baum besteht grundsätzlich aus zwei Dingen: Knoten und Blätter. Ein Knoten hat Kinder (andere Knoten oder Blätter), ein Blatt nicht.
Knoten kannst Du so implementieren, dass sie ganz einfach die SQL Fragmente ihrer Blätter verketten. Das wäre eine Funktionalität, die man im AbstractConstruct implementieren kann. Bei Blättern ist es anders, da muss jedes Blatt seine eigene Logik haben, wie es sein SQL Fragment erzeugt. Und diese Logik solltest Du in der Construct-Klasse des Blattes implementieren.
Es gibt grundsätzlich zwei Ansätze. Einmal kann der Konstruktor die ganze Arbeit machen und das SQL Fragment des Knotens komplett zusammensetzen. Aber dann brauchst Du keine Klassen, das ist ein rein funktionaler Ansatz. Nachteil ist, dass Du die Generierung nicht validieren kannst. Die Teile eines SQL Statements haben Abhängigkeiten, z.B. Table Aliase, und bei einem funktionalen Ansatz kann das SELECT Statement nicht validieren, ob die Alias-Angaben der Columns in den Tables überhaupt vorkommen.
Ein Objektorientierter Ansatz würde im ersten Schritt einen vollständigen Syntaxbaum konstruieren und die SQL Generierung als zweiten Schritt machen.
Die Idee hier lautet Polymorphie; es gibt eine getSQL Methode (oder wie Du das nennst) in AbstractConstruct, die von Knotenklassen überschrieben werden kann, aber nicht muss. Blattklassen sollten sie überschreiben, weil sie nicht andere SQL Fragmente aggregieren, sondern aus dem Nichts erzeugen.
Wenn man den Generator so baut, dann könnten sich einige deiner Probleme in Luft auflösen. Wenn Du ihn schon so gebaut hast und die Probleme trotzdem hast, dann übersehe ich sie bei meiner abstrakten Überlegung möglicherweise...
Rolf
sumpsi - posui - obstruxi