Auf der Suche nach einem Design-Muster, das den Huuuge ersetzt, wenn es sich um einen Objekttyp handelt

8

OK, ich suche einen Code, der ungefähr so ​​aussieht:

%Vor%

Nun wäre ein Ansatz, alle Objekte o , die als Parameter verwendet werden, so zu implementieren, dass sie eine Schnittstelle wie

implementieren %Vor%

Aber das Problem dabei ist, dass ich nicht möchte, dass alle meine Objekte diese Schnittstelle implementieren - die Logik für die Do-Methode gehört nicht wirklich zu ihnen. Welches Muster sollte ich verwenden, um damit umzugehen?

Ich vermute etwas wie eine Reihe von Implementierungen von

%Vor%

könnte besser sein. Ich würde eine Implementierung für jeden der Objekttypen haben, mit denen ich es tun möchte, aber dann habe ich dieses neue Problem. Ich würde irgendwann eine Methode wie

brauchen %Vor%

Aber muss das massiv geändert werden? Sollte ich eine Klasse mit vielen Methoden wie

definieren %Vor%

Dies hat das Problem im Vergleich zur generischen Version, dass Sie zur Laufzeit keine neuen Typen hinzufügen können. Gibt es da etwas listiges, was man mit einem DI-Container in GetPropsGeneric machen kann, um den Container aufzulösen? Danke!

    
mcintyre321 20.11.2008, 17:48
quelle

6 Antworten

6

Wenn Sie eine switch-Anweisung (oder eine Reihe von if-Anweisungen) sehen, die den Typ eines Objekts überprüfen, ist dies ein Big Red Flag für eine fehlende Basisklasse oder Schnittstelle. Mit anderen Worten, der Code sollte sich auf Polymorphie stützen und den Objekttyp nicht testen

Wenn Sie die Basisklasse nicht ändern oder eine Schnittstelle implementieren können, haben Sie wahrscheinlich noch ein Wörterbuch, um dynamisches Dispatching zu simulieren. In C # können Sie einen anonymen Delegaten für die Methode verwenden, die die Besetzung enthält

Wie beim Zugriff auf Eigenschaften, wenn die Eigenschaften nicht übereinstimmen und der Zugriff über Reflektion keine Option ist, müssen Sie möglicherweise die Eigenschaftswerte in der obigen Methode / dem obigen Delegaten extrahieren und sie stattdessen an eine generische Funktion übergeben

    
Steven A. Lowe 20.11.2008, 17:55
quelle
2

Es sieht so aus, als ob Sie C # verwenden. Ich glaube, dass Sie "Erweiterungsmethoden" erstellen können, die bereits vorhandenen Klassen beifügen.

Ein anderer Ansatz besteht darin, für jeden Typ Handlerdelegate zu erstellen und Referenzen auf die Delegaten in einer Hashtabelle zu speichern, die nach Objekttyp codiert ist.

Dann könnte Ihre "DoSomething" -Methode einfach den geeigneten Delegaten nach dem Typ des übergebenen Objekts suchen und ausführen.

    
bobwienholt 20.11.2008 17:54
quelle
0

Ein reales Beispiel wäre hilfreicher. Wenn Sie einfach die Implementierung einer Methode für eine Familie verwandter Klassen ändern, verwenden Sie, wie @Steven A. Lowe sagt, am besten Polymorphie und verwenden dafür die Unterklassenbeziehungen. Wenn die Klassen nicht an "is a" -Beziehungen teilnehmen, können andere Muster wie Besucher geeigneter sein. p>     

tvanfosson 20.11.2008 18:06
quelle
0

Polymorphismus ist die Antwort, bei der ein Basisobjekt übergeben wird. Es ist jedoch wesentlich mehr Vortex- und Semantikkomplexität, als Sie vielleicht möchten.

Es erfordert, dass Ihre Funktionalität irgendwie in die abgeleiteten Klassen und eine "virtuelle" Funktion, die implementiert werden soll, verschoben wird.

    
Paul Nathan 20.11.2008 18:07
quelle
0

Ich denke, das ist eher eine Frage für eine Aspektorientierte Programmierung.

Ich möchte, dass Ihre DoSomething-Methode eine ICanHaveSomethingDone-Schnittstelle als Parameter verwendet. Dann würde ich die ICanHaveSomethinhgDone-Schnittstelle definieren und daraus Subklammern (eine für jedes Objekt, zu der Sie etwas tun möchten), die die DoSomethingToMe implementieren, für jede implementierende Klasse anders ableiten. Jeder von ihnen nimmt einfach einen Konstruktor des Typs, mit dem Sie etwas tun wollen, so dass Sie beim Aufruf von DoSomething tatsächlich eine Factory aufrufen (sehr einfach, indem Sie einfach eine Instanz Ihrer ICanHaveSomethingDone-Klasse vom Eingabetyp zu erstellen) Erstellen Sie eine Instanz einer Klasse, die die DoSomethingToMe-Methode implementiert und über den richtigen Code für das zugrunde liegende Objekt verfügt.

Denken Sie im Grunde so; Sie definieren einen Schnittstellenvertrag, den die Parameterobjekte implementieren sollen; und Definieren von "Dekoration" in Form von Unterklassen Ihres Objekts und der Schnittstelle, die spezifische Implementierungen des Schnittstellenverhaltens implementieren (und somit den Vertrag erfüllen) für Ihre spezifische Klasse. Auf diese Weise können Sie die Implementierung der DoSomething-Methode für jede Klasse vollständig von der Quelle dieser Klassen trennen.

Eine andere Sache, die das tut; Dies bedeutet, dass Sie zur Laufzeit neue Typen hinzufügen können, wenn Sie Ihre Factory zu einem DI-Container machen. indem Sie die neuen Typen in Ihren Factory-Container injizieren, mit denen Sie etwas tun möchten, solange Sie eine Implementierung der Aktion haben, die Sie definiert als eine Klasse definieren möchten, die von Ihrer Schnittstelle und von dieser Klasse abgeleitet ist , Du bist gut. Sie können das Verhalten sogar zur Laufzeit definieren, ohne dass die abgeleitete Klasse implementiert werden muss, wenn Sie einen vollständigen AOP-Ansatz implementieren. Definieren Sie Ihre Schnittstelle, definieren Sie Ihre Verhaltensweisen in den Aktionen und parametrisieren Sie die Implementierung Ihrer abgeleiteten Klassen, um zur Laufzeit die gewünschten Verhaltensweisen mit dem übergebenen Objekt zu erstellen. Aber das ist kompliziert ...: -)

Spring AOP ist übrigens großartig über dieses Zeug. Ich habe es gelesen.

    
Paul Sonier 20.11.2008 18:09
quelle
0

Ich stimme Steven zu, auch dieser Problemkontext hat mich daran erinnert, dass es sich um ein doppeltes Dispatching-Problem handelt, daher könnte das Besuchermuster die richtige Lösung sein. Aber es ist offensichtlich, dass in Ihrer Hierarchie einige Schnittstellendefinitionen fehlen.

    
baris.aydinoz 01.04.2010 14:07
quelle