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