DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world
Demo Ruby Style Mixin In Java
This needs more work to be complete. Will it ever be useful?
public class MixinTest
{
/*
* The Demo
*/
interface Chimera extends Lion, Goat, Serpent, Animal {}
public static void main(String[] args)
{
Chimera chimera = (Chimera) MixinFactory.create(Chimera.class, new AnimalImpl());
System.out.println("The Chimera: ");
chimera.roar();
chimera.stomp();
chimera.slither();
chimera.action("Sing a song");
}
/*
* The Interfaces
*/
public interface Lion
{
void roar();
}
public interface Goat
{
void stomp();
}
public interface Serpent
{
void slither();
}
public interface Animal
{
void action(String description);
}
/*
* The Implementations
*/
public static class LionImpl implements Lion
{
private Animal animal;
public LionImpl(Animal animal)
{
this.animal = animal;
}
public void roar()
{
animal.action("Roars with lion head");
}
}
public static class GoatImpl implements Goat
{
private Animal animal;
public GoatImpl(Animal animal)
{
this.animal = animal;
}
public void stomp()
{
animal.action("Stomps with goat foot");
}
}
public static class SerpentImpl implements Serpent
{
private Animal animal;
public SerpentImpl(Animal animal)
{
this.animal = animal;
}
public void slither()
{
animal.action("Slithers with serpent tail");
}
}
public static class AnimalImpl implements Animal
{
public void action(String description)
{
System.out.println(description);
}
}
/*
* The Guts
*/
public static class MixinFactory
{
private static class MixinInvocationHandler implements InvocationHandler
{
private Map implMap = new HashMap();
public MixinInvocationHandler(Class clazz, Object core)
{
for (int i = 0; i < clazz.getInterfaces().length; i++)
{
Class anInterface = clazz.getInterfaces()[i];
try
{
Class delegateClass = Class.forName(anInterface.getName()+"Impl");
Constructor delegateConstructor = findBestMatchConstrustor(delegateClass, core.getClass());
if(delegateConstructor != null)
{
implMap.put(anInterface, delegateConstructor.newInstance(new Object[] {core}));
}
else
{
implMap.put(anInterface, core);
}
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
Object delegate = implMap.get(method.getDeclaringClass());
return delegate.getClass().getDeclaredMethod(method.getName(), method.getParameterTypes()).invoke(delegate, args);
}
private static Constructor findBestMatchConstrustor(Class delegateClass, Class coreClass)
{
if(coreClass == null)
{
return null;
}
try
{
return delegateClass.getConstructor(new Class[] {coreClass});
}
catch (NoSuchMethodException e)
{
Class[] interfaces = coreClass.getInterfaces();
for (int i = 0; interfaces != null && i < interfaces.length; i++)
{
Class interfaceClass = interfaces[i];
Constructor delegateConstructor = findBestMatchConstrustor(delegateClass, interfaceClass);
if(delegateConstructor != null)
{
return delegateConstructor;
}
}
Constructor delegateConstructor = findBestMatchConstrustor(delegateClass, coreClass.getSuperclass());
if(delegateConstructor != null)
{
return delegateConstructor;
}
}
return null;
}
}
public static Object create(Class clazz, Object core)
{
return Proxy.newProxyInstance(clazz.getClassLoader(), new Class [] {clazz}, new MixinInvocationHandler(clazz, core));
}
}
}





