Java Objekt als Service in Runtime registrieren

dbausnnd

Aktives Mitglied
Hallo,

ich habe eine frage zur vorgehensweise um Objekte einer Runtime als ein Service zu registrieren. Ich habe ein Objekt welches über Service Methoden verfügt. Diese Service Methoden sollenvon anderen Objekten verwendet werden die keine Referenz auf das Service Objekt besitzen. Ich würde einen Service Mediator dazwischen setzen, bei dem sich Service Objekte registrieren können. Die ServiceMethoden benötigen Parameter die ich typensicher definieren möchte.

Serivce Klasse:
Java:
public class ServiceClass implements ServiceMediatorListener{

	ServiceMediator mediator;
	String name = "ServiceName";

	public ServiceClass(ServiceMediator mediator) {
		this.mediator = mediator;
		ServiceParameter<Date> parm = new ServiceParameter<Date>("Datum", new Date());
		mediator.registerService(this, name, parm);
	}

	@Override
	public void callService(ServiceParameter... parm) {
		System.out.println(String.format("Service '%s' wurde gestartet mit %s Parametern.", name, parm.length));
		
		System.out.println();
		
		for(int i = 0; i < parm.length; i++){
			System.out.println(String.format("%s. Parameter = %s", i, parm[i]));
		}
	}


}

ServiceMediator:
Java:
public class ServiceMediator {

	Map<String, ServiceMediatorListener> mapListener = new Hashtable<String, ServiceMediatorListener>();
	Map<String, ServiceParameter> mapParameter = new Hashtable<String, ServiceParameter>();
	
	public void registerService(ServiceMediatorListener listener, String serviceName, ServiceParameter<?> parameter){
		
		this.mapListener.put(serviceName, listener);
		this.mapParameter.put(serviceName, parameter);
		
	}
	
	public ServiceParameter<?> getServiceparameter(String servicName){
		return mapParameter.get(servicName);
	}
	
	public void callService(String serviceName, ServiceParameter<?>... parm){
		if(mapListener.containsKey(serviceName)){
			mapListener.get(serviceName).callService(parm);
		}
	}
}

ServiceMediatorListener:
Java:
public interface ServiceMediatorListener<T> {

	
	public void callService(ServiceParameter<?>... parm);

}

ServiceParameter
Java:
public class ServiceParameter<T> {

	String name;
	T value;
	
	public ServiceParameter(String name, T value) {
		this.name = name;
		this.value = value;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public T getValue() {
		return value;
	}

	public void setValue(T value) {
		this.value = value;
	}
	
	

}

Consumer Klasse
Java:
public class ConsumerClass {

	ServiceMediator mediator;
	
	public ConsumerClass(ServiceMediator mediator) {
		this.mediator = mediator;
	}
	
	public void start(){
		
		ServiceParameter<?> parm = mediator.getServiceparameter("ServiceName");
		
		parm.setValue(new Date());
		
		mediator.callService("ServiceName", parm);
		
	}

}

Das Problem ist, das das ServiceParameter Objekt so nicht typensicher gefüllt werden kann. Gibt es hier einen besseren Ansatz?

Gruß

dbausnnd
 
Zuletzt bearbeitet von einem Moderator:
Da seh ich so ein paar Dinge die man bestimmt verbessern kann:

Zum einen sollte dein Service die Klasse ServiceMediator nicht kennen. Ein Service sollte eine für sich abgeschlossene Einheit sein, die nicht weiß wo oder in welchem Kontext sie eingesetzt wird.

Im "ServiceMediatorListener" fehlen mir zudem noch ein paar Methoden, die den "Listener" komplett beschreiben. Und wenn du die Klasse auch noch mit einem Generic für den Parameter versiehst, sollte dein Eingangsproblem auch schon gelöst sein:
Java:
public interface ServiceMediatorListener<P> {// ParameterTyp als Generic
  String getName(); // wie heißt der Service?
  ServiceParameter<P> getParameter(); // Welchen Parameter benötigt der Service
  callService(ServiceParameter<P> param); // wie gehabt
 }
Vielleicht bietet es sich auch an, den "ServiceMediatorListener" einfach in "Service" umzubenennen? Irgendwie wäre die Aufgabe dieses Interfaces dann klarer.

Als nächstes fällt mir die Initialisierung auf. Wie willst deine Service-Klassen erzeugen? Im Moment registriert sich der Service selbst, wenn er erzeugt wird. Wie soll das aussehen?
Java:
ServiceMediator mediator = new ServiceMediator();
new SomeService(mediator); // Neues Objekt erzeugen ohne es zu speichern!?
Ich würde es für besser und übersichtlicher halten, wenn du die Services explizit am Mediator registrierst:
Java:
ServiceMediator mediator = new ServiceMediator();
mediator.registerService(new SomeService()); // Service selbst weiß nix vom Mediator

Da der Service nun Parametrisiert ist, kannst du den Parameter auch relativ typsicher abfragen:
Java:
public <T> ServiceParameter<T> getServiceparameter(String servicName){
return (ServiceParameter<T>) mapParameter.get(servicName); // diesen unsauberen cast wirst du kaum vermeiden können
}
 
public <T> void callService(String serviceName, ServiceParameter<T>... parm){
  if(mapListener.containsKey(serviceName)){
    ((ServiceMediatorListener<T>)mapListener.get(serviceName)).callService(parm); //und diesen cast auch nicht.
  }
}

Um es noch etwas "typsicherer" zu bekommen könntest anfangen den Class-Typ dem Parameter mitzugeben und diesen auch bei der Service-Anfrage zu verlangen. Somit könntest du den Typ zur Laufzeit vergleichen, um dann einen geeignete Exception werfen.
 

Zurück
Oben