Instanceof vermeiden

WolfBauer

Erfahrenes Mitglied
Hallo,
ich versuch eine einfaches EventSystem zu nutzen. Dabei möchte ich allerdings instanceof vermeiden und es soll möglich sein, dass neue EventArgs erstellt werden können.

Beispiel:
Code:
public class test {
    public void send(IMyArgs args);
}

public interface IMyArgs {
}

public class MyArgs1 {
}

public class MyArgs2 {
}

Die Klasse test soll nun, je nach Args verschiedenen Verarbeitungen starten. Möglich wäre dies bspw. über ein instanceof-Vergleich. So hat kann man auch beliebige neue Args in Zukunft verwenden. Dies möchte ich allerdings vermeiden.

Eine weitere Möglichkeit wäre nun mit IDs zu arbeiten. Bspw. Strings. Die ist meiner Meinung aber auch unschön, da man so Args mit gleichen Strings nicht verhindern kann. Und auch die Fehleranfälligkeit recht hoch ist.

Mit Enums kann man auch nicht arbeiten, da diese nicht ableitbar sind. D. h. wenn ich später neue Args einführen will, müsste ich die alten Enums verändern.

Hat irgendwer dafür eine schöne Lösung oder eine Idee?

Grüße
 
Klassisches Anfängerproblem. :) Lösung ist ein Umdrehen des Designs. Das Interface bekommt eine Methode, die dein test-Client rufen kann, ohne die Implementierung zu kennen. Ziel ist es hierbei, dass der Client einen generischen Anteil der Abarbeitung enthält, während die Implementierungen des Interfaces den für sie spezifischen Teil der Abarbeitung enthalten. Wenn dein Client wirklich nur ein IMyArgs bekommt, ist es sinnvoller direkt auf der IMyArgs Instanz zu rufen.

Gruß
Ollie
 
Änfangerproblem... Kann sein :). Dann versuch ich mal mein Problem ein wenig zu erweitern.

Und zwar geht es Konkret um einen OSGI-Kontext und der Kommunikation zwischen zwei Services. Hierbei werden zwischen BundleA Daten an BundleB, welches einen Service Implementiert (also ist test im Beispiel eigentlich ein Interface) gesendet. Anhand dieser Daten, sollen dann verschiedenen Verarbeitungsschritte eingeleitet werden.
Diese Event-Daten enthalten, also auch Informationen, um was für ein Event es sich handelt. Zum Beispiel: löschen alle Daten, kopiere Daten, baue Verbindung auf.

Das Problem:
"während die Implementierungen des Interfaces den für sie spezifischen Teil der Abarbeitung enthalten": dies geht nicht, da die Architektur vorschreibt, dass die Logik voll und ganz im Service liegt.

Ziel ist übrigens bei der ganzen Geschichte, dass Leute die später das Services anbieten wollen, eigene EventsArgs definieren können, welche in ihrer Implementierung verarbeitet werden. Somit ist man nicht mehr auf die vordefinierten löschen alle Daten, kopiere Daten, baue Verbindung angewiesen und kann sich noch eins zum lösche Daten erstellen.

Ursprung war eine solche Struktur:
Code:
public interface test {
    public void delFile(Sring name);
    public void copyFile(Sring name);
    public void renameFile(Sring name);
}

Vielleicht habe ich aber wieder was übersehen.

Vielen Dank trotzdem schon mal,
Grüße,
Wolf


Übrigens war ein Fehler im Beispiel:

Code:
public class test {
    public void send(IMyArgs args);
}

public interface IMyArgs {
}

public class MyArgs1 implements IMyArgs {
}

public class MyArgs2 implements IMyArgs  {
}
 
Zuletzt bearbeitet:
Und habe ich mal eine mögliche Lösung, die allerdings noch nicht alle Anforderungen erfüllt:

Code:
public abstract class EventType {
	private String id;

	protected AbstractEventType(String id) {
		this.id = id;
	}

	public String getValue() {
		return id;
	}
}

public class FileEventType extends EventType {
		
	public static FileEventType DEL_FILE = new FileEventType("DEL_FILE");
	public static FileEventType COPY_FILE = new FileEventType("COPY_FILE");
	
	protected FileEventType(String id) {
		super(id);
	}
}

public interface Event<SenderType, ValueType, Type extends EventType> {
	public SenderType getSender();
	public ValueType getValue;
	public Type getType();
}

public class FileEvent extends Event<MyInterfaceSender, File, FileEventType> {
}

public class test {
    public void sendEvent(Event args);
}
 
Ich blick in deinem Design noch nicht ganz durch. Auf der einen Seite sagst du, dass dieser Eventmechanismus (vielleicht trifft das Wort auch nciht ganz das was es eigentlich ist) erweiterbar sein soll, auf dere anderen Seite die Aussage, dass die Logik im Service implementiert sein soll. Ich vermute du versuchst sowas ähnliches wie eine Pluginarchitektur zu stricken. Sowas kann man völlig generisch über ein Commandpattern (ein Interface für alle Plugins) machen oder halt dedizierte Interfaces für ein bestimmtes Subset an Plugins, die dann an einen oder mehrere Pluginclients gebunden werden (per Dependency Injection, OSGi Declarative Services oder Spring Dynamic Modules).

Was mir an deinem Beispiel noch konkret auffällt, ist die Komplexität des Event Interfaces. Duch die Generics wird das schon recht unübersichtlich. Grad wenn andere über dieses Interface dein Programm erweitern sollen sollte das so einfach wie möglich sein.

Gruß
Ollie
 
Vielleicht reden wir auch aneinander vorbei. Es geht um einen OSGI-Kontext mit Deklarativen Services.

Nun gibt es ein BundleA und ein BundleB. BundleA nutzt nun ServiceB, welches BundleB bereit stellt. Nun kann BundleA die Methoden aus BundleB nutzen. Alles schön und gut.

Nun soll ServiceB allerdings einen Methode zum Senden von "Events" bereitstellen. D. h. BundleA kann ServiceB beliebige Nachrichten senden, auf welche der Services dann reagiert. Unter anderem enthalten die "Events" einen sender an den nun asyncron Rückmeldungen gesandt werden können.

Bei dem Beispiel oben ist dies gegeben. Möchte man nun neue BundleA2 und bspw. BundleB2 implementieren, welche über neue "FileEvents" kommunizieren kann einfach von FileEventType abgeleitet werden und neue statische Attribute hinzugefügt werden.

Die Erweiterbarkeit bezieht sich also auf die Kommunikationsebene und so auf die Möglichkeit neue Plug-Ins zu erstellen ohne den Service zu ändern.

Grüße,
Wolf
 
Nochmal, ich finde das Design etwas unorthodox... das Events einen Sender mitführen, an den dann Rückmeldungen gesendet werden klingt irgendwie nach durcheinander bzw. fehlendem Separation of concerns.

Was du da schilderst klingt eher nach nem Einsatzgebiet von MessageDriven Middleware, wie JMS bzw. einem Integrationsszenario, was darauf aufbaut. Halt irgendeine Technologie, die Events und Nachrichten als primäres Konzept hat. Warum ausgerechnet ein Service diese Rolle übernehmen soll, versteh ich nicht. Gerade wenn es mit Asynchonität losgeht für eigentlich kaum ein weng an JMS vorbei.

Gruß
Ollie
 

Neue Beiträge

Zurück