Last active
December 19, 2015 03:29
-
-
Save UnquietCode/5890203 to your computer and use it in GitHub Desktop.
An encapsulation of the State Pattern in Java (http://en.wikipedia.org/wiki/State_pattern)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface ContextAware<T> { | |
void beforeMethod(AtomicReference<T> context); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Stateful { | |
/** | |
* This is a type-checking method, which gets around Java's inability | |
* to handle multiple bounds such as "V extends T & ContextAware<T>". | |
* | |
* @param value initial value, which should extends T | |
* @param contextAware initial value, which should extend ContextAware<T> | |
* @return a new proxy object | |
*/ | |
public static <T> T getProxy(Class<T> clazz, T value, ContextAware<T> contextAware) { | |
if (value != contextAware) { | |
throw new IllegalArgumentException("This method expects the same object for both parameters."); | |
} | |
return getProxy(clazz, value); | |
} | |
@SuppressWarnings("unchecked") | |
private static <T> T getProxy(final Class<T> clazz, final Object initial) { | |
if (initial == null) { | |
throw new NullPointerException("needs a value to start"); | |
} | |
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new InvocationHandler() { | |
Object value = initial; | |
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | |
AtomicReference<Object> ref = new AtomicReference<>(value); | |
((ContextAware) value).beforeMethod(ref); | |
Object retval = method.invoke(value, args); | |
value = ref.get(); | |
return retval; | |
} | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface DoesStuff { | |
void doSomething(int i); | |
} | |
static class SomethingDoerA implements DoesStuff, ContextAware<DoesStuff> { | |
AtomicReference<DoesStuff> context; | |
@Override | |
public void beforeMethod(AtomicReference<DoesStuff> context) { | |
this.context = context; | |
} | |
@Override | |
public void doSomething(int i) { | |
System.out.println("hello "+i); | |
context.set(new SomethingDoerB()); | |
} | |
} | |
static class SomethingDoerB implements DoesStuff, ContextAware<DoesStuff> { | |
AtomicReference<DoesStuff> context; | |
@Override | |
public void beforeMethod(AtomicReference<DoesStuff> context) { | |
this.context = context; | |
} | |
@Override | |
public void doSomething(int i) { | |
System.out.println("what's up "+(i+100)); | |
context.set(new SomethingDoerA()); | |
} | |
} | |
@Test | |
public void test() { | |
SomethingDoerA initial = new SomethingDoerA(); | |
DoesStuff doer2 = StatefulX.getProxy(DoesStuff.class, initial, initial); | |
doer2.doSomething(1); | |
doer2.doSomething(2); | |
doer2.doSomething(3); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment