asato <asato@ncfreak.com>
最終更新日 : 2002/9/26 (2002/9/26 より)
State パターン
拡張/変更がありえる部分
Context に対する新たな状態依存メソッドの追加
改善となりえる部分
AspectJ を使った State に関するテクニックの種類
状態依存メソッドの局所化
実装:
サンプルコード:
package dp.state; public class Context { private State state; public void request() { state.handle(); } public void setState(State state) { this.state = state; } }
package dp.state; public interface State { public void handle(); }
package dp.state; public class ConcreteStateA implements State { public void handle() { System.out.println("ConcreteStateA - handle"); } }
package dp.state; public class ConcreteStateB implements State { public void handle() { System.out.println("ConcreteStateB - handle"); } }
package dp; import dp.state.*; public class Client { public static void main(String[] args) { Context context = new Context(); context.setState( new ConcreteStateA() ); context.request(); context.newRequest(); context.setState( new ConcreteStateB() ); context.request(); context.newRequest(); } }
package dp.state; privileged aspect StateAspect { public void Context.newRequest() { this.state.newHandle(); } public abstract void State.newHandle(); public void ConcreteStateA.newHandle() { System.out.println("ConcreteStateA - newHandle"); } public void ConcreteStateB.newHandle() { System.out.println("ConcreteStateB - newHandle"); } }
ConcreteStateA - handle ConcreteStateA - newHandle ConcreteStateB - handle ConcreteStateB - newHandle
State パターンの導入
package dp.state; public class Context { public static final int STATE_A = 0; public static final int STATE_B = 1; private int state = STATE_A; public void request() { if (state == STATE_A) { System.out.println("STATE A"); } else if (state == STATE_B) { System.out.println("STATE B"); } } public void setState(int state) { this.state = state; } }
package dp; import dp.state.*; public class Client { public static void main(String[] args) { Context context = new Context(); context.request(); context.setState( Context.STATE_B ); context.request(); context.setState( Context.STATE_C ); context.request(); } }
package dp.state; import java.util.Map; import java.util.HashMap; public aspect StateAspect { private Map stateMap = new HashMap(); public StateAspect() { stateMap.put( new Integer(Context.STATE_A), new ConcreteStateA() ); stateMap.put( new Integer(Context.STATE_B), new ConcreteStateB() ); stateMap.put( new Integer(Context.STATE_C), new ConcreteStateC() ); } declare parents: ConcreteState* implements State; protected interface State { } protected class ConcreteStateA { } protected class ConcreteStateB { } protected class ConcreteStateC { } public abstract void State.handle(); public static final int Context.STATE_C = 2; private State Context.contextState; private Context State.context; private void State.setContext(Context context) { this.context = context; } public void (ConcreteStateA || ConcreteStateB).handle() { context.request(); } public void ConcreteStateC.handle() { System.out.println("STATE C"); } pointcut setState(Context context, int state) : this(context) && args(state) && set(int Context.state); after(Context context, int state) : setState(context, state) { context.contextState = (State)stateMap.get( new Integer(state) ); } pointcut request(Context context) : !within(StateAspect) && target(context) && call( void Context.request() ); void around(Context context) : request(context) { context.contextState.setContext(context); context.contextState.handle(); } }
STATE A STATE B STATE C