Annotations, Enum, AspectJ and the State pattern
March 24, 2006 Leave a comment
The combination of annotations and AspectJ is a hot topic worth exploring when using JSE 5.0. Recently we were discussing if this combination can be used to implement part of the State pattern. Even though I couldn’t think of any practical value for this, I implemented this code. The following code has meta-data associated with methods and this meta-data has the next state hardcoded in it. I have used Enum,annotations and AspectJ but I haven’t checked this for bugs. The State pattern example is the one by Robert C. Martin. See Aspect-Oriented Design Pattern Implementations for implementations of the GOF patterns using AOP.
package com.state;
public class Turnstile {
public void lock(){
System.out.println( "Locking" );
}
public void unlock(){
System.out.println( "UnLocking" );
}
public void alarm(){
System.out.println( "Security Breach" );
}
}
package com.state;
public class TurnstileMachine extends Turnstile {
private TurnstileState state;
public void coin() {
state.coin( this );
}
public void pass() {
state.pass( this );
}
public void setState(TurnstileState state) {
this.state = state;
System.out.println( "Changing state to " + state );
}
}
package com.state;
public abstract class TurnstileState {
public abstract void coin( TurnstileMachine t );
public abstract void pass( TurnstileMachine t );
}
package com.state;
public class UnlockedState extends TurnstileState {
@Override
public void coin(TurnstileMachine t) {
}
@Override
@StateChanger(EnumState.UNLOCK)
public void pass(TurnstileMachine t) {
//t.setState( this );
t.unlock();
}
}
package com.state;
public enum EnumState {
LOCK {
{ state = new LockedState(); }
},
UNLOCK {
{ state = new UnlockedState(); }
};
TurnstileState state;
}
package com.state;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention( RetentionPolicy.RUNTIME )
@Target({ ElementType.METHOD })
public @interface StateChanger {
public EnumState value() default EnumState.LOCK;
}
package com.state;
public aspect StateAspect {
pointcut stateChanger( TurnstileState t,
StateChanger sc,
TurnstileMachine m)
: execution( @StateChanger * *(..) )&& @annotation(sc) && this(t) && args(m);
void around( TurnstileState t,
StateChanger sc,
TurnstileMachine m ) : stateChanger( t,sc, m ){
proceed( t, sc, m );
m.setState( sc.value().state);
}
}