4 Stimmen

Instanz einer Klasse auf der Grundlage einer anderen Klasse erstellen

In Java habe ich die Klasse X und Schnittstelle Y und dann eine Reihe von Klassen A1 .. Und das erweitern X und umsetzen Y . Ich mache dann einen Wrapper/Adapter für jede der Klassen A1..An (d.h., A1'..An' ).

Jetzt, in der Client-Klasse C erhalte ich die Liste der Instanzen der Schnittstelle Y ( ArrayList < Y > ).

An dieser Stelle möchte ich für jede Instanz in der Liste eine neue Instanz einer Klasse erstellen Ax' (aus A1'..An' ) basierend auf der Tatsache, welche Instanz von Y in der Liste steht. Für A1 zu machen A1' usw.

Mein Zweifel ist, wie kann ich das erreichen, ohne if .. else if ... und (Instanz der) Konstruktion. Kann ich hier irgendwie Vererbung verwenden?

Ich habe einige Entwurfsmuster überprüft, aber ich konnte keine Lösung finden, wie man die Klassen erstellt, die auf der Instanz einer anderen Klasse basieren.

Für jede Hilfe und jeden Ratschlag wären wir dankbar. Danke.

2voto

Ilya Punkte 28356
for(Y y : ArrayList < Y >)  
{  
   y.getClass().newInstance();  
}  

wenn ich Ihre Frage richtig verstanden habe...

エディトリアル

abstract class X implements Y 
{
    Y getInstance();
}

class A1 extends X
{
    void someMethod()
    {
        getInstance(); // return instance of A1_
    }
}

class A1_ extends A1
{
    Y getInstance()
    {
        return new A1_();
    }
}    

EDIT2

Wenn Sie die Instanz des Elternteils im Kind erhalten möchten, können Sie Folgendes tun

this.getClass().getSuperclass().newInstance();

1voto

AlexR Punkte 111534

Sie können verwenden Class.forName() Methode, um einen Wrapper zu erstellen. Die Zuordnung zwischen der Klasse A1...AN und dem Klassennamen des Wrappers kann entweder hart kodiert, in Eigenschaften oder in einer XML-Datei gespeichert werden oder, wenn Sie möchten, mit Hilfe von Anmerkungen, die auf Ihren A1...AN-Klassen platziert werden.

1voto

Gilberto Torrezan Punkte 4835
for(Y y : ArrayList < Y >)  
{  
  Class<?> clazz = Class.forName(y.getClass().getName()+"Adapter");
  YAdapter ya = (YAdapter)clazz.newInstance();
}

Eine Mischung aus beiden Antworten.

1voto

Alexei Kaigorodov Punkte 12793

Erstellen. HashMap<Class<Y>, Class<?>> . Erstellen Sie für jedes An und A'n eine Beziehung: map.put(An.class, A'n.class) .

Dann, für jede obj in ArrayList , get A' class: Class aa=map.get(obj.getClass()) . Erstellen Sie dann eine Instanz der Klasse aa, entweder mit aa.newInstance() (und dann weitergeben obj über Setter), oder mit einem Konstruktor, der Reflection verwendet (und die obj als Parameter).

1voto

Brian Punkte 16654

Zunächst müssen Sie eine Möglichkeit finden, die Adapter (A' 1 .. A' n ) mit den konkreten Instanzen (A 1 .. A n ). Dies geschieht am besten mit einer Map<Class<?>, Constructor<?>> . Eine gute Möglichkeit wäre, eine Registrierung zu erstellen:

public class AdapterRegistry {
    private static final Map<Class<?>, Constructor<?>> adapterMap =
            new HashMap<Class<?>, Constructor<?>>();

    public static void register(Class<?> interfaceClass, Class<?> concreteClass, Class<?> adapterClass) 
            throws NoSuchMethodException {
        // Check for the constructor
        Constructor<?> constructor = adapterClass.getConstructor(interfaceClass);
        adapterMap.put(concreteClass, constructor);
    }

    public static <T, V extends T> T wrap(V v) {
        Class<?> concreteClass = v.getClass();
        try {
            Constructor<?> constructor = adapterMap.get(concreteClass);
            if (constructor != null) {
                return (T) constructor.newInstance(v);
            }
        } catch (Exception ex) {
            // TODO Log me
        }
        return null;
    }
}

Dann muss man nur noch die Adapter erstellen:

public class Adapter implements Y {
    private Y innerY;

    public Adapter(Y innerY) {
        this.innerY = innerY;
    }

    // Implement Y
}

Und registrieren Sie Ihre(n) Adapter:

AdapterRegistry.register(Y.class, A1.class, Adapter1.class);
AdapterRegistry.register(Y.class, A2.class, Adapter1.class);
AdapterRegistry.register(Y.class, A3.class, Adapter2.class);
// ...
AdapterRegistry.register(An.class, AdapterM.class);

Beachten Sie, dass Sie auf diese Weise mehrere Adapter für dieselbe Klasse registrieren können, wenn Sie möchten. Wenn eine Teilmenge konkreter Klassen auf die gleiche Weise behandelt werden soll, müssen Sie nur denselben Adapter für alle registrieren.

Als Nächstes holen Sie den Wrapper:

for (Y y : yList) {
    Y adapter = AdapterRegistry.wrap(y);
    // Do something with the adapter
}

Dies ist mit gewissen Einschränkungen verbunden:

  • Sie müssen einen Konstruktor in jedem Adapter haben, der das konkrete Objekt durch seine Schnittstelle .
  • Die Schnittstelle muss die Methoden enthalten, die Sie ändern möchten (wenn Sie Y als Typ für innerY Sie können dies ändern, so dass Sie Zugriff auf Nicht-Schnittstellen-Methoden haben, aber dann müssen Sie Casting durchführen).

Sie können dann auch Ihre AdapterRegistry auch in anderen Teilen Ihres Programms, da es Generika verwendet.

Sagen Sie mir Bescheid, wenn es Probleme mit dem Code gibt und Sie ihn nicht lösen können.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X