Archief - [PROG][JAVA] functie uitvoeren adhv string

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

passero

Legacy Member
Het is 2 jaar geleden dat ik nog wat java gedaan heb maar kheb er plots weer zin in en heb een oud projectje van onder het stof gehaald en ben dit beetje aan het aanpassen. Betere design, beter ontwerp,...

Een van de zaken die ik zou willen aanpassen is het dynamisch maken van functies. Het is een programma waar de gebruiker functies kan aanroepen vanuit een commandbox. Die functies staan gedefinieerd in een XML waar ook het aantal parameters, help enzo staan gedefinieerd.
Momenteel staat het uitvoeren van zo een methode in een structuur zoals hieronder:

Code:
if(methode.equals("exit"))
{
   doeExit();
}
if(methode.equals("clear"))
{
   doeClear();
}
if(methode.equals("doeIets"))
{
  doeIets(parameters);
}

parameters is een ArrayList die de parameters bijhoudt voor het uitvoeren van de methode die parameters verwacht.

Het spreekt voor zich dat wanneer ik een functie toevoeg aan de XML en aan de klasse, ik ook die if structuur moet aanpassen.

Ik zou dus een systeem willen waarbij ik gemakkelijk nieuwe module's kan toevoegen adhv nieuwe XML files. Die xml files bevatten dan eigenlijk het pad naar de klasse en defenitie van de functie.
Ik zou dan ook eigenlijk het equivalent van de eval functie gebruiken in PHP maar dan in java zodat het dynamisch is, alleen weet ik niet direct hoe ik in java functies kan oproepen adhv een string

EDIT: na een beetje zoeken heb ik gemerkt dat dit dus niet echt mogelijk is in java en dat zo een structuur wijst op een designprobleemke... nu ja, dat dacht ik al.
IK heb ook even zitten zoeken en blijkbaar kunnnen het command en interpreter pattern mij hier wel wat helpen maar mss toch even jullie advies hoe ik dit best aanpak?

daigon

Legacy Member
Je kan gebruik maken van het Class object. Echter moeten al je commando classes wel voldoen aan de javabean specificaties dus een lege constructor zonder parameters ;). En je moet de fully qualified classname gevens dus de volledige package informatie.

Verder kan je best gebruik maken van overerving, zodat alle commandos op dezelfde manier worden aangeroepen bij het uitvoeren.

Abstracte superklasse
Code:
package be.daigon.dynamicLoad;

public abstract class Command {
	public abstract void execute();
}

exit commando
Code:
package be.daigon.dynamicLoad;

public class exitCommand extends Command {

	@Override
	public void execute() {
		System.out.println("exit execute");
	}

}

clear commando
Code:
package be.daigon.dynamicLoad;

public class clearCommand extends Command {

	@Override
	public void execute() {
		System.out.println("clear executed");
	}

}

Class instantieren en terug sturen // heb er niet veel veiligheidschecks rond gedaan bijvoorbeeld classcastexception kan nog optreden enz...
Code:
package be.daigon.dynamicLoad;

public class ClassFactory {

	
	public Command getClassFromFullName(String fqClassName) {
		try {
			return (Command) Class.forName(fqClassName).newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
}

De run code
Code:
package be.daigon.dynamicLoad;

public class Start {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ClassFactory factory = new ClassFactory();
		Command command;
		command = factory.getClassFromFullName("be.daigon.dynamicLoad.clearCommand");
		if (command != null) {
			command.execute();
		}
		
		command = factory.getClassFromFullName("be.daigon.dynamicLoad.exitCommand");
		if (command != null) {
			command.execute();
		}
	}

}

Verder zou je het nog kunnen uitbreiden met dynamische argument passing van java 5.0 in de functie. Heb er zelf nog niet met gewerkt dus kan niet direct uitleggen(zelf eerst eens proberen ;)).

Edit
-----

Je kan in de aanmaak functie eventueel de Commando klasses een functie geven om via setters de variabelen in te geven of een hashmap en die opvullen met de parameters en value's die inde xml file staan. hashmap is natuurlijk dynamischer en eenvoudig itereerbaar.

passero

Legacy Member
lijkt me zeer goede code.
Ik had ondertussen wat patterns zitten bekijken en kwam op een gelijkaardig systeem uit.

Ik heb nu een interface Methode die elke methode moet implementeren en ik groepeer die in een module. Die module krijgt een XML bestand binnen met de klasnamen van de methoden enzo. IN mijn programma ga ik dan een module loader steken waarbij je dan gemakkelijk andere modules kan toevoegen.

Ice

Legacy Member
Hierboven vermelde oplossing is idd ook een goed plan, als je echter met variabele lijsten van parameters zit wordt het al wat moeilijker. Je zou hierboven dan kunnen uitbreiden naar execute (Object[] args) en elke methode laten bepalen wat ze met hun arguments doen.

Een andere oplossing is om dmv Reflection de juiste methoden gaan uitvoeren.
Aangezien Reflection niet zo extreem performant is (toch zal het waarschijnlijk geen probleem zijn voor u) kan je wel uw gevonden methodes cachen in dictionary ofzo.

http://java.sun.com/docs/books/tutorial/reflect/member/methodInvocation.html
en dan vooral het stukje: "Invoking Methods with a Variable Number of Arguments"

passero

Legacy Member
hetgeen ik nu doe is 1 execute functie per methode en die krijgt inderdaad een collection mee van parameters.
Binnen de execute methode kijk ik dan welke variante het is, hoeveel parameters het zijn en van welk type ze zijn.
Misschien dat dit ook dynamischer kan maar het is toch al relatief goed en flexibel vind ik
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan