Dynamisch zur Laufzeit getypte Modelle erzeugen.


Thomas Darimont

Premium-User
Hallo!

Hier mal ein Beispiel wie man dynamisch zur Laufzeit getypte Datenmodelle erzeugen kann:
Java:
/**
 * 
 */
package de.tutorials;


/**
 * @author Tom
 * 
 */
public class DataModelProxyFactoryExample {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		IDataModel dataModel = DataModelProxyFactory.createModel(IDataModel.class);
		dataModel.setData("ABC");
		dataModel.setValue(1337);
		System.out.println(dataModel.getData());
		System.out.println(dataModel.getValue());
		
		System.out.println("###############");
		
		IGenericDataModel<String, Integer> genericDataModel = DataModelProxyFactory.createModel();
		
		genericDataModel.setBubu("Hallo");
		genericDataModel.setGugu(4711);
		
		System.out.println(genericDataModel.getBubu());
		System.out.println(genericDataModel.getGugu());
	}
}
Java:
package de.tutorials;

interface IDataModel{
	String getData();
	void setData(String s);
	
	int getValue();
	void setValue(int value);
	
}

/**
 * 
 */
package de.tutorials;

/**
 * @author Thomas.Darimont
 *
 */
public interface IGenericDataModel<TBubu,TGugu> {
	TBubu getBubu();
	void setBubu(TBubu data);
	
	TGugu getGugu();
	void setGugu(TGugu data);
}
Java:
/**
 * 
 */
package de.tutorials;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class DataModelWrapper implements InvocationHandler {
	Map<String, Object> propertyNameToValueMap = new HashMap<String, Object>();

	Class<?> wrappedClass;

	public DataModelWrapper(Class<?> wrappedClass) {
		this.wrappedClass = wrappedClass;
	}

	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		if (wrappedClass.equals(method.getDeclaringClass())) {

			String methodName = method.getName();

			if (methodName.startsWith("get")) {
				String attributeName = getAttributeName(method.getName());
				return propertyNameToValueMap.get(attributeName);
			} else if (methodName.startsWith("set")) {
				String attributeName = getAttributeName(method.getName());
				propertyNameToValueMap.put(attributeName, args[0]);
				return null;
			}

		}
		return null;
	}

	private String getAttributeName(String name) {
		return Character.toLowerCase(name.charAt(3)) + name.substring(4);
	}
}
Java:
/**
 * 
 */
package de.tutorials;

import java.lang.reflect.Proxy;

public class DataModelProxyFactory {
	@SuppressWarnings("unchecked")
	public static <TTargetType> TTargetType createModel(Class<?> clazz) {
		return (TTargetType)Proxy.newProxyInstance(clazz.getClassLoader(),
				new Class[] { clazz }, new DataModelWrapper(clazz));
	}

	public static <TTargetType> TTargetType createModel(TTargetType ... args) {
		Class<?> targetInterface = args.getClass().getComponentType();
		return createModel(targetInterface);
	}
}
Hierbei muss nun nun nur noch die Interfaces für die domänenspezifischen Datenmodelle spezifizieren
und über die DataModelProxyFactory wird dann dynamisch ein auf das Interfaces getyptes Model erzeugt.
Auf dieses Modell kann man dann über die im Interface definierten Methoden (getyped) zugreifen.

equals/hashCode/toString muss man dann auch entsprechend intercepten...

Btw. in C# schaut das ganze dann so aus:
http://www.tutorials.de/forum/net-cafe/259066-getypte-datenmodelle-nur-mit-interfaces-und-dynamic-proxies.html

Gruß Tom
 

Neue Beiträge