最終更新日 : 2004/5/15 (2002/9/26 より)
Strategy パターン
AspectJ による Strategy パターンの実装
実装 1 |
実装 2 |
実装 3 |
実装 4 |
実装 5 |
実装 6 |
実装 7 |
実装 8 |
実装 9 |
考慮点
まえがき
使う 保持 Client --------------> Context ----------------> Strategy | │ +-> | │ | | × | 実装 | 生成 │ | +-----------------> ConcreteStrategy -----+必要なコードは:
感想
AspectJ を使った Strategy に関するテクニックの種類
力ずく AspectJ 的 Strategy
結果:
サンプルコード:
package dp.strategy; public class Context { public void contextInterface() { } }
package dp.strategy; public class ConcreteStrategyA { public void method() { System.out.println("ConcreteStrategyA"); } }
package dp.strategy; public class ConcreteStrategyB { public void perform() { System.out.println("ConcreteStrategyB"); } }
package dp; import dp.strategy.*; public class Client { public static void main(String[] args) { Context context = new Context(); context.contextInterface(); } private static aspect ClientAspect extends StrategyAspect { pointcut newContext() : withincode( void main(String[]) ) && call( Context.new() ); Context around() : newContext() { Context context = new Context(); setStrategy( context, new ConcreteStrategyB() ); return context; } } }
package dp.strategy; public abstract aspect StrategyProtocol { protected interface Strategy { } protected interface StrategyContext { } private Strategy StrategyContext.strategy; private void StrategyContext.setStrategy(Strategy strategy) { this.strategy = strategy; } private Strategy StrategyContext.getStrategy() { return strategy; } protected void setStrategy(StrategyContext context, Strategy strategy) { context.setStrategy(strategy); } protected Strategy getStrategy(StrategyContext context) { return context.strategy; } protected abstract pointcut contextInterface(StrategyContext context); void around(StrategyContext context) : contextInterface(context) { perform( context.getStrategy() ); } protected pointcut perform() : call(void perform(Strategy) ); private void perform(Strategy strategy) { } }
package dp.strategy; public abstract aspect StrategyAspect extends StrategyProtocol { declare parents : Context implements StrategyContext; declare parents : ConcreteStrategyA implements Strategy; declare parents : ConcreteStrategyB implements Strategy; protected pointcut contextInterface(StrategyContext context) : target(context) && call( void Context.contextInterface() ); void around(ConcreteStrategyA str) : args(str) && perform() { perform(str); } void around(ConcreteStrategyB str) : args(str) && perform() { perform(str); } private void perform(ConcreteStrategyA strategy) { strategy.method(); } private void perform(ConcreteStrategyB strategy) { strategy.perform(); } }
ConcreteStrategyB
考慮すべき要求:
Strategy の導入
package dp.strategy; public class Context { public static final int STRATEGY_A = 0; public static final int STRATEGY_B = 1; private int strategy; public Context(int strategy) { this.strategy = strategy; } public void contextInterface() { switch (strategy) { case STRATEGY_A : strategyA(); break; case STRATEGY_B : strategyB(); break; } } private void strategyA() { System.out.println("StrategyA"); } private void strategyB() { System.out.println("StrategyB"); } }
package dp.strategy; public class MyStrategy { public void algorithmInterface() { System.out.println("My Strategy"); } }
package dp; import dp.strategy.*; public class Client { public static void main(String[] args) { Context context = new Context( Context.STRATEGY_A ); context.contextInterface(); context.setStrategy( new MyStrategy() ); context.contextInterface(); context.setStrategy( Context.STRATEGY_B ); context.contextInterface(); } }
package dp.strategy; import java.util.Map; import java.util.HashMap; privileged aspect StrategyAspect { private static Map strategyMap = new HashMap(); static { strategyMap.put( new Integer(Context.STRATEGY_A), new OriginalStrategy() ); strategyMap.put( new Integer(Context.STRATEGY_B), new OriginalStrategy() ); } private static Strategy getOriginalStrategy(int strategy) { return (Strategy)strategyMap.get( new Integer(strategy) ); } declare parents: MyStrategy implements Strategy; declare parents: OriginalStrategy implements Strategy; private static class OriginalStrategy { public void algorithmInterface() { context.contextInterface(); } } protected interface Strategy { } public abstract void Strategy.algorithmInterface(); public void Strategy.setContext(Context context) { this.context = context; } private Context Strategy.context; private Strategy Context.strategyObject; public void Context.setStrategy(Strategy strategy) { this.strategyObject = strategy; } public void Context.setStrategy(int strategy) { this.strategy = strategy; } private Strategy Context.getStrategy() { return strategyObject; } pointcut contextInterface(Context context) : !within(StrategyAspect) && target(context) && call( void Context.contextInterface() ); void around(Context context) : contextInterface(context) { context.getStrategy().algorithmInterface(); } pointcut setOriginalStrategy(Context context, int strategy) : target(context) && args(strategy) && set(int Context.strategy); after(Context context, int strategy) : setOriginalStrategy(context, strategy) { Strategy strat = getOriginalStrategy( strategy ); strat.setContext( context ); context.setStrategy( strat ); } }
StrategyA My Strategy StrategyB
実装:
実装 - その 2
段階 - その 1
public class Context { private Strategy strategy; public void setStrategy(Strategy strategy) { this.strategy = strategy; } public void contextInterface() { strategy.algorithmInterface(); } }
public interface Strategy { public void algorithmInterface(); }
public aspect ConcreteStrategyA implements Strategy perthis( this(Context) ) { public void algorithmInterface() { System.out.println("ConcreteStrategyA"); } public static ConcreteStrategyA getInstance(Context context) { return ConcreteStrategyA.aspectOf(context); } }
public class Client { public static void main(String[] args) { Context context = new Context(); context.setStrategy( ConcreteStrategyA.getInstance(context) ); context.contextInterface(); // ConcreteStrategyA } }
段階 - その 2
public class Context { private Strategy strategy; private String state; public Context(String state) { this.state = state; } public void setStrategy(Strategy strategy) { this.strategy = strategy; } public void contextInterface() { strategy.algorithmInterface(); } }
privileged aspect ConcreteStrategyA implements Strategy perthis( this(Context) ) { private Context context; public void algorithmInterface() { System.out.println("ConcreteStrategyA - " + context.state); } public static ConcreteStrategyA getInstance(Context context) { ConcreteStrategyA strategy = ConcreteStrategyA.aspectOf(context); strategy.context = context; return strategy; } }
public class Client { public static void main(String[] args) { Context context = new Context("aaa"); context.setStrategy( ConcreteStrategyA.getInstance(context) ); context.contextInterface(); // ConcreteStrategyA - aaa } }
実装 - その 3 [2]
[2] を元に少しの修正を加えています。
public class Context { public void contextInterface() { } }
public aspect Strategy pertarget( method(Context) ) { private pointcut method(Context context) : target(context) && call(void Context.contextInterface() ); public static final int STRATEGY_1 = 1; public static final int STRATEGY_2 = 2; private int Context.strategy = 0; public Context.new(int strategy) { this.strategy = strategy; } void around(Context context) : method(context) { if (context.strategy == STRATEGY_1) { strategy1(); } else if (context.strategy == STRATEGY_2) { strategy2(); } else { defaultStrategy(); } } private void strategy1() { System.out.println("strategy1"); } private void strategy2() { System.out.println("strategy2"); } public void defaultStrategy() { System.out.println("defaultStrategy"); } }
public class Client { public static void main(String[] args) { Context context = new Context(Strategy.STRATEGY_1); context.contextInterface(); // "strategy1" } }
実装 - その 4
段階 - その 1
public class Context { public void contextInterface() { System.out.println("Context.contextInterface()"); } }
public aspect StrategyAspect pertarget( target(Context) ) { private boolean isActive; public void activate() { this.isActive = true; } void around() : call( void Context.contextInterface() ) { if (isActive) { algorithmInterface(); } else { proceed(); } } private void algorithmInterface() { System.out.println("StrategyAspect.algorithmInterface()"); } }
public class Client { public static void main(String[] args) { Context context = new Context(); context.contextInterface(); StrategyAspect.aspectOf(context).activate(); context.contextInterface(); } }実行結果:
Context.contextInterface() StrategyAspect.algorithmInterface()
段階 - その 2 : 複数の strategy が必要になったら?
public class Context { public void contextInterface() { System.out.println("Context.contextInterface()"); } }
public abstract aspect AbstractStrategyAspect pertarget( target(Context) ) { private boolean isActive; private Context context; private AbstractStrategyAspect Context.strategy; public void activate() { this.isActive = true; if (context.strategy != null) { context.strategy.deactivate(); } context.strategy = this; } public void deactivate() { this.isActive = false; } after(Context context): target(context) && initialization( Context.new() ) { this.context = context; } void around() : call( void Context.contextInterface() ) { if (isActive) { algorithmInterface(); } else { proceed(); } } protected abstract void algorithmInterface(); }
public aspect StrategyAspectA extends AbstractStrategyAspect { protected void algorithmInterface() { System.out.println("StrategyAspectA.algorithmInterface()"); } }
public aspect StrategyAspectB extends AbstractStrategyAspect { protected void algorithmInterface() { System.out.println("StrategyAspectB.algorithmInterface()"); } }
public class Client { public static void main(String[] args) { Context context = new Context(); context.contextInterface(); StrategyAspectA.aspectOf(context).activate(); context.contextInterface(); StrategyAspectB.aspectOf(context).activate(); context.contextInterface(); } }実行結果:
Context.contextInterface() StrategyAspectA.algorithmInterface() StrategyAspectB.algorithmInterface()
段階 - その 3 : 再利用可能にできるか?
public class MyContext { public void contextInterface() { System.out.println("MyContext.contextInterface()"); } }
public abstract aspect StrategyProtocol pertarget( target(Context) ) { protected interface Context { } private boolean isActive; private Context context; private StrategyProtocol Context.strategy; public void activate() { this.isActive = true; if (context.strategy != null) { context.strategy.deactivate(); } context.strategy = this; } public void deactivate() { this.isActive = false; } after(Context context): target(context) && initialization( Context.new() ) { this.context = context; } protected abstract pointcut callContextInterface(); void around() : callContextInterface() { if (isActive) { algorithmInterface(); } else { proceed(); } } protected abstract void algorithmInterface(); }
public abstract aspect AbstractStrategyAspect extends StrategyProtocol { declare parents : MyContext implements Context; protected pointcut callContextInterface() : call(void MyContext.contextInterface() ); protected void algorithmInterface() { myAlgorithmInterface(); } protected abstract void myAlgorithmInterface(); }
public aspect StrategyAspectA extends AbstractStrategyAspect { protected void myAlgorithmInterface() { System.out.println("StrategyAspectA.myAlgorithmInterface()"); } }
public aspect StrategyAspectB extends AbstractStrategyAspect { protected void myAlgorithmInterface() { System.out.println("StrategyAspectB.myAlgorithmInterface()"); } }
public class Client { public static void main(String[] args) { MyContext context = new MyContext(); context.contextInterface(); StrategyAspectA.aspectOf(context).activate(); context.contextInterface(); StrategyAspectB.aspectOf(context).activate(); context.contextInterface(); } }実行結果:
MyContext.contextInterface() StrategyAspectA.myAlgorithmInterface() StrategyAspectB.myAlgorithmInterface()
バイトコード・ウィービングシナリオ
ライブラリ側 (lib パッケージ):
public class MyContext { public void contextInterface() { System.out.println("MyContext.contextInterface()"); } }アプリケーション側 (app パッケージ):
public abstract aspect StrategyProtocol pertarget( target(Context) ) { protected interface Context { } private boolean isActive; private Context context; private StrategyProtocol Context.strategy; public void activate() { this.isActive = true; if (context.strategy != null) { context.strategy.deactivate(); } context.strategy = this; } public void deactivate() { this.isActive = false; } after(Context context): target(context) && initialization( Context.new() ) { this.context = context; } protected abstract pointcut callContextInterface(); void around() : callContextInterface() { if (isActive) { algorithmInterface(); } else { proceed(); } } protected abstract void algorithmInterface(); }
import lib.MyContext; public abstract aspect AbstractStrategyAspect extends StrategyProtocol { declare parents : MyContext implements Context; protected pointcut callContextInterface() : call(void MyContext.contextInterface() ); protected void algorithmInterface() { myAlgorithmInterface(); } protected abstract void myAlgorithmInterface(); }
public aspect StrategyAspectA extends AbstractStrategyAspect { protected void myAlgorithmInterface() { System.out.println("StrategyAspectA.myAlgorithmInterface()"); } }
public aspect StrategyAspectB extends AbstractStrategyAspect { protected void myAlgorithmInterface() { System.out.println("StrategyAspectB.myAlgorithmInterface()"); } }
import lib.MyContext; public class Client { public static void main(String[] args) { MyContext context = new MyContext(); context.contextInterface(); StrategyAspectA.aspectOf(context).activate(); context.contextInterface(); StrategyAspectB.aspectOf(context).activate(); context.contextInterface(); } }実行結果:
MyContext.contextInterface() StrategyAspectA.myAlgorithmInterface() StrategyAspectB.myAlgorithmInterface()
実装 - その 5
段階 - その 1
public class Context { public void contextInterface() { System.out.println("Context.contextInterface()"); } }
public aspect StrategyAspect { private Map roleMap = new HashMap(); public void apply(Context context) { ContextRole role = null; if ( roleMap.containsKey(context) == false ) { role = new ContextRole(); roleMap.put(context, role); } else { role = (ContextRole)roleMap.get(context); } Strategy.aspectOf(role).activate(); } private ContextRole getRole(Context context) { return (ContextRole)roleMap.get(context); } private static class ContextRole { } private static aspect Strategy pertarget( target(ContextRole) || target(Context) ) { private boolean isActive; public void activate() { this.isActive = true; } void around(Context context) : target(context) && call( void Context.contextInterface() ) && if (StrategyAspect.aspectOf().getRole(context) != null) { ContextRole role = StrategyAspect.aspectOf().getRole(context); if ( Strategy.aspectOf( role ).isActive ) { algorithmInterface(); } else { proceed(context); } } public void algorithmInterface() { System.out.println("Strategy.algorithmInterface()"); } } }
public class Client { public static void main(String[] args) { Context context = new Context(); context.contextInterface(); StrategyAspect.aspectOf().apply(context); context.contextInterface(); } }実行結果:
Context.contextInterface() Strategy.algorithmInterface()
実装 - その 6
段階 - その 1
public class Context { public void contextInterface() { System.out.println("Context.contextInterface()"); } }
public aspect StrategyAspect pertarget( target(ContextRole) ) { private boolean isActive; public void activate() { this.isActive = true; } private static aspect Strategy { void around(Context context) : target(context) && call( void Context.contextInterface() ) { if (StrategyAspect.aspectOf(context).isActive) { StrategyAspect.aspectOf(context).algorithmInterface(); } else { proceed(context); } } } private void algorithmInterface() { System.out.println("StrategyAspect.algorithmInterface()"); } private static class ContextRole { } private static aspect Impl { private Map roleMap = new HashMap(); StrategyAspect around(Object context) : args(context) && call(StrategyAspect StrategyAspect.aspectOf(Object)) { Object role = null; if ( roleMap.containsKey(context) == false) { role = new ContextRole(); roleMap.put(context, role); } else { role = roleMap.get(context); } return proceed(role); } } }
public class Client { public static void main(String[] args) { Context context = new Context(); context.contextInterface(); StrategyAspect.aspectOf(context).activate(); context.contextInterface(); } }実行結果:
Context.contextInterface() StrategyAspect.algorithmInterface()
段階 - その 2 : 複数の Strategy
public abstract aspect AbstractStrategyAspect pertarget( target(ContextRole) ) { private boolean isActive; public void activate() { this.isActive = true; } protected boolean isActive() { return isActive; } protected static class ContextRole { } private static aspect Impl { private Map roleMap = new HashMap(); Object around(Object context) : args(context) && call(AbstractStrategyAspect+ AbstractStrategyAspect+.aspectOf(Object) ) { Object role = null; if ( roleMap.containsKey(context) == false) { role = new ContextRole(); roleMap.put(context, role); } else { role = roleMap.get(context); } return proceed(role); } } }
public aspect StrategyAspectA extends AbstractStrategyAspect { private static aspect Strategy { void around(Context context) : target(context) && call( void Context.contextInterface() ) { if ( StrategyAspectA.aspectOf(context).isActive() ) { StrategyAspectA.aspectOf(context).algorithmInterface(); } else { proceed(context); } } } private void algorithmInterface() { System.out.println("StrategyAspectA.algorithmInterface()"); } }
public aspect StrategyAspectB extends AbstractStrategyAspect { private static aspect Strategy { void around(Context context) : target(context) && call( void Context.contextInterface() ) { if ( StrategyAspectB.aspectOf(context).isActive() ) { StrategyAspectB.aspectOf(context).algorithmInterface(); } else { proceed(context); } } } private void algorithmInterface() { System.out.println("StrategyAspectB.algorithmInterface()"); } }
public class Client { public static void main(String[] args) { Context context = new Context(); context.contextInterface(); StrategyAspectA.aspectOf(context).activate(); context.contextInterface(); System.out.println(); context = new Context(); context.contextInterface(); StrategyAspectB.aspectOf(context).activate(); context.contextInterface(); } }実行結果:
Context.contextInterface() StrategyAspectA.algorithmInterface() Context.contextInterface() StrategyAspectB.algorithmInterface()
段階 - その 3 : 複数の Strategy - その 2
public abstract aspect AbstractStrategyAspect pertarget( target(ContextRole) ) { private boolean isActive; private ContextRole role; public void activate() { this.isActive = true; if (role.strategy != null) { role.strategy.deactivate(); } role.strategy = this; } public void deactivate() { this.isActive = false; } protected boolean isActive() { return isActive; } protected abstract void algorithmInterface(); private static ContextRole getContextRole(Object context) { return (ContextRole)Impl.aspectOf().roleMap.get(context); } after(ContextRole role): target(role) && initialization( ContextRole.new() ) { this.role = role; } private static aspect Strategy { void around(Object context) : target(context) && call( void Context.contextInterface() ) && if (getContextRole(context) != null) { AbstractStrategyAspect strategy = getContextRole(context).strategy; if ( strategy != null && strategy.isActive() ) { strategy.algorithmInterface(); } else { proceed(context); } } } protected static class ContextRole { private AbstractStrategyAspect strategy; } private static aspect Impl { private Map roleMap = new HashMap(); Object around(Object context) : args(context) && call(AbstractStrategyAspect+ AbstractStrategyAspect+.aspectOf(Object) ) { Object role = null; if ( roleMap.containsKey(context) == false) { role = new ContextRole(); roleMap.put(context, role); } else { role = roleMap.get(context); } return proceed(role); } } }
public aspect StrategyAspectA extends AbstractStrategyAspect { protected void algorithmInterface() { System.out.println("StrategyAspectA.algorithmInterface()"); } }
public aspect StrategyAspectB extends AbstractStrategyAspect { protected void algorithmInterface() { System.out.println("StrategyAspectB.algorithmInterface()"); } }
public class Client { public static void main(String[] args) { Context context1 = new Context(); context1.contextInterface(); StrategyAspectA.aspectOf(context1).activate(); context1.contextInterface(); StrategyAspectB.aspectOf(context1).activate(); context1.contextInterface(); System.out.println(); Context context2 = new Context(); context2.contextInterface(); StrategyAspectB.aspectOf(context2).activate(); context2.contextInterface(); StrategyAspectA.aspectOf(context2).activate(); context2.contextInterface(); } }実行結果:
Context.contextInterface() StrategyAspectA.algorithmInterface() StrategyAspectB.algorithmInterface() Context.contextInterface() StrategyAspectB.algorithmInterface() StrategyAspectA.algorithmInterface()
段階 - その 4 : 再利用可能にできるか?
public abstract aspect StrategyAspectProtocol pertarget( target(ContextRole) ) { private boolean isActive; private ContextRole role; public void activate() { this.isActive = true; if (role.strategy != null) { role.strategy.deactivate(); } role.strategy = this; } public void deactivate() { this.isActive = false; } protected boolean isActive() { return isActive; } protected abstract void algorithmInterface(); private static ContextRole getContextRole(Object context) { return (ContextRole)Impl.aspectOf().roleMap.get(context); } after(ContextRole role): target(role) && initialization( ContextRole.new() ) { this.role = role; } protected static abstract aspect Strategy { protected abstract pointcut callContextInterface(); void around(Object context) : target(context) && callContextInterface() && if (getContextRole(context) != null) { StrategyAspectProtocol strategy = getContextRole(context).strategy; if ( strategy != null && strategy.isActive() ) { strategy.algorithmInterface(); } else { proceed(context); } } } protected static class ContextRole { private StrategyAspectProtocol strategy; } private static aspect Impl { private Map roleMap = new HashMap(); Object around(Object context) : args(context) && call(StrategyAspectProtocol+ StrategyAspectProtocol+.aspectOf(Object) ) { Object role = null; if ( roleMap.containsKey(context) == false) { role = new ContextRole(); roleMap.put(context, role); } else { role = roleMap.get(context); } return proceed(role); } } }
public abstract aspect AbstractStrategyAspect extends StrategyAspectProtocol { protected void algorithmInterface() { myAlgorithmInterface(); } protected abstract void myAlgorithmInterface(); protected static aspect StrategyImpl extends Strategy { protected pointcut callContextInterface() : call( void Context.contextInterface() ); } }
public aspect StrategyAspectA extends AbstractStrategyAspect { protected void myAlgorithmInterface() { System.out.println("StrategyAspectA.myAlgorithmInterface()"); } }
public aspect StrategyAspectB extends AbstractStrategyAspect { protected void myAlgorithmInterface() { System.out.println("StrategyAspectB.myAlgorithmInterface()"); } }
public class Client { public static void main(String[] args) { Context context1 = new Context(); context1.contextInterface(); StrategyAspectA.aspectOf(context1).activate(); context1.contextInterface(); StrategyAspectB.aspectOf(context1).activate(); context1.contextInterface(); System.out.println(); Context context2 = new Context(); context2.contextInterface(); StrategyAspectB.aspectOf(context2).activate(); context2.contextInterface(); StrategyAspectA.aspectOf(context2).activate(); context2.contextInterface(); } }実行結果:
Context.contextInterface() StrategyAspectA.myAlgorithmInterface() StrategyAspectB.myAlgorithmInterface() Context.contextInterface() StrategyAspectB.myAlgorithmInterface() StrategyAspectA.myAlgorithmInterface()
使用例
package lib; public class MyContext { public void contextInterface() { System.out.println("MyContext.contextInterface()"); } }アプリケーション側:
package app; import java.util.Map; import java.util.HashMap; import lib.MyContext; public abstract aspect AbstractStrategyAspect pertarget( target(ContextRole) ) { private boolean isActive; private ContextRole role; public void activate() { this.isActive = true; if (role.strategy != null) { role.strategy.deactivate(); } role.strategy = this; } public void deactivate() { this.isActive = false; } protected boolean isActive() { return isActive; } protected abstract void algorithmInterface(); private static ContextRole getContextRole(Object context) { return (ContextRole)Impl.aspectOf().roleMap.get(context); } after(ContextRole role): target(role) && initialization( ContextRole.new() ) { this.role = role; } private static aspect Strategy { void around(Object context) : target(context) && call( void MyContext.contextInterface() ) && if (getContextRole(context) != null) { AbstractStrategyAspect strategy = getContextRole(context).strategy; if ( strategy != null && strategy.isActive() ) { strategy.algorithmInterface(); } else { proceed(context); } } } protected static class ContextRole { private AbstractStrategyAspect strategy; } private static aspect Impl { private Map roleMap = new HashMap(); Object around(Object context) : args(context) && call(AbstractStrategyAspect+ AbstractStrategyAspect+.aspectOf(Object) ) { Object role = null; if ( roleMap.containsKey(context) == false) { role = new ContextRole(); roleMap.put(context, role); } else { role = roleMap.get(context); } return proceed(role); } } }
package app; public aspect StrategyAspectA extends AbstractStrategyAspect { protected void algorithmInterface() { System.out.println("StrategyAspectA.algorithmInterface()"); } }
package app; public aspect StrategyAspectB extends AbstractStrategyAspect { protected void algorithmInterface() { System.out.println("StrategyAspectB.algorithmInterface()"); } }
package app; import lib.MyContext; public class Client { public static void main(String[] args) { MyContext context1 = new MyContext(); context1.contextInterface(); // "MyContext.contextInterface()" StrategyAspectA.aspectOf(context1).activate(); context1.contextInterface(); // "StrategyAspectA.algorithmInterface()" StrategyAspectB.aspectOf(context1).activate(); context1.contextInterface(); // "StrategyAspectB.algorithmInterface()" System.out.println(); MyContext context2 = new MyContext(); context2.contextInterface(); // "MyContext.contextInterface()" StrategyAspectB.aspectOf(context2).activate(); context2.contextInterface(); // "StrategyAspectB.algorithmInterface()" StrategyAspectA.aspectOf(context2).activate(); context2.contextInterface(); // "StrategyAspectA.algorithmInterface()" } }実行結果:
MyContext.contextInterface() StrategyAspectA.algorithmInterface() StrategyAspectB.algorithmInterface() MyContext.contextInterface() StrategyAspectB.algorithmInterface() StrategyAspectA.algorithmInterface()
使用例 - その 2
package lib; public class MyContext { public void contextInterface() { System.out.println("MyContext.contextInterface()"); } }ライブラリ拡張側:
package lib2; import java.util.Map; import java.util.HashMap; public abstract aspect StrategyAspectProtocol pertarget( target(ContextRole) ) { private boolean isActive; private ContextRole role; public void activate() { this.isActive = true; if (role.strategy != null) { role.strategy.deactivate(); } role.strategy = this; } public void deactivate() { this.isActive = false; } protected boolean isActive() { return isActive; } protected abstract void algorithmInterface(); private static ContextRole getContextRole(Object context) { return (ContextRole)Impl.aspectOf().roleMap.get(context); } after(ContextRole role): target(role) && initialization( ContextRole.new() ) { this.role = role; } protected static abstract aspect Strategy { protected abstract pointcut callContextInterface(); void around(Object context) : target(context) && callContextInterface() && if (getContextRole(context) != null) { StrategyAspectProtocol strategy = getContextRole(context).strategy; if ( strategy != null && strategy.isActive() ) { strategy.algorithmInterface(); } else { proceed(context); } } } protected static class ContextRole { private StrategyAspectProtocol strategy; } private static aspect Impl { private Map roleMap = new HashMap(); Object around(Object context) : args(context) && call(StrategyAspectProtocol+ StrategyAspectProtocol+.aspectOf(Object) ) { Object role = null; if ( roleMap.containsKey(context) == false) { role = new ContextRole(); roleMap.put(context, role); } else { role = roleMap.get(context); } return proceed(role); } } }
package lib2; import lib.MyContext; public abstract aspect AbstractStrategyAspect extends StrategyAspectProtocol { protected void algorithmInterface() { myAlgorithmInterface(); } protected abstract void myAlgorithmInterface(); protected static aspect StrategyImpl extends Strategy { protected pointcut callContextInterface() : call( void MyContext.contextInterface() ); } }拡張されたライブラリを使うアプリケーション側:
package app; import lib2.AbstractStrategyAspect; public aspect StrategyAspectA extends AbstractStrategyAspect { protected void myAlgorithmInterface() { System.out.println("StrategyAspectA.myAlgorithmInterface()"); } }
package app; import lib2.AbstractStrategyAspect; public aspect StrategyAspectB extends AbstractStrategyAspect { protected void myAlgorithmInterface() { System.out.println("StrategyAspectB.myAlgorithmInterface()"); } }
package app; import lib.MyContext; public class Client { public static void main(String[] args) { MyContext context1 = new MyContext(); context1.contextInterface(); StrategyAspectA.aspectOf(context1).activate(); context1.contextInterface(); StrategyAspectB.aspectOf(context1).activate(); context1.contextInterface(); System.out.println(); MyContext context2 = new MyContext(); context2.contextInterface(); StrategyAspectB.aspectOf(context2).activate(); context2.contextInterface(); StrategyAspectA.aspectOf(context2).activate(); context2.contextInterface(); } }実行結果:
MyContext.contextInterface() StrategyAspectA.myAlgorithmInterface() StrategyAspectB.myAlgorithmInterface() MyContext.contextInterface() StrategyAspectB.myAlgorithmInterface() StrategyAspectA.myAlgorithmInterface()
実装 - その 7 : PerTargetAspect を使って
使用例
ライブラリ側:
package lib; public class MyContext { public void contextInterface() { System.out.println("MyContext.contextInterface()"); } }ライブラリ拡張側:
package lib2; import java.util.Map; import java.util.HashMap; import peraspect.PerTarget; import peraspect.PerTargetAspect; public abstract aspect StrategyAspectProtocol implements PerTarget { private boolean isActive; private ContextRole role; public void activate() { this.isActive = true; if (role.strategy != null && role.strategy != this) { role.strategy.deactivate(); } role.strategy = this; } public void deactivate() { this.isActive = false; } protected boolean isActive() { return isActive; } protected abstract void algorithmInterface(); private static ContextRole getContextRole(Object context) { return (ContextRole)Impl.aspectOf().roleMap.get(context); } protected static abstract aspect Strategy { protected abstract pointcut callContextInterface(); void around(Object context) : target(context) && callContextInterface() && if (getContextRole(context) != null) { StrategyAspectProtocol strategy = getContextRole(context).strategy; if ( strategy != null && strategy.isActive() ) { strategy.algorithmInterface(); } else { proceed(context); } } } public static class ContextRole { private StrategyAspectProtocol strategy; } private static aspect Impl { private Map roleMap = new HashMap(); Object around(Object context) : args(context) && call(StrategyAspectProtocol+ StrategyAspectProtocol+.aspectOf(Object) ) { ContextRole role = null; if ( roleMap.containsKey(context) == false) { role = new ContextRole(); roleMap.put(context, role); } else { role = (ContextRole)roleMap.get(context); } StrategyAspectProtocol strategy = (StrategyAspectProtocol)proceed(role); if (strategy.role == null) { strategy.role = role; } return strategy; } } protected static abstract aspect AbstractPerTargetImpl extends PerTargetAspect.Impl { protected pointcut targetObj(Object targetObj) : target(targetObj) && target(ContextRole); } }
package lib2; import lib.MyContext; public abstract aspect AbstractStrategyAspect extends StrategyAspectProtocol { protected void algorithmInterface() { myAlgorithmInterface(); } protected abstract void myAlgorithmInterface(); protected static aspect StrategyImpl extends Strategy { protected pointcut callContextInterface() : call( void MyContext.contextInterface() ); } protected static abstract aspect AbstractPerTarget extends AbstractPerTargetImpl { } }拡張されたライブラリを使うクライアント側:
package app; import lib2.AbstractStrategyAspect; import peraspect.PerTarget; public aspect StrategyAspectA extends AbstractStrategyAspect { protected void myAlgorithmInterface() { System.out.println("StrategyAspectA.myAlgorithmInterface() - " + this); } protected static aspect PerTargetImpl extends AbstractPerTarget { protected PerTarget getAspect() { return StrategyAspectA.aspectOf(); } } public static StrategyAspectA aspectOf(Object obj) { return (StrategyAspectA)StrategyAspectA.aspectOf().getAspect(obj); } }
package app; import lib2.AbstractStrategyAspect; import peraspect.PerTarget; public aspect StrategyAspectB extends AbstractStrategyAspect { protected void myAlgorithmInterface() { System.out.println("StrategyAspectB.myAlgorithmInterface() - " + this); } protected static aspect PerTargetImpl extends AbstractPerTarget { protected PerTarget getAspect() { return StrategyAspectB.aspectOf(); } } public static StrategyAspectB aspectOf(Object obj) { return (StrategyAspectB)StrategyAspectB.aspectOf().getAspect(obj); } }
package app; import lib.MyContext; public class Client { public static void main(String[] args) { MyContext context1 = new MyContext(); context1.contextInterface(); StrategyAspectA.aspectOf(context1).activate(); context1.contextInterface(); StrategyAspectB.aspectOf(context1).activate(); context1.contextInterface(); System.out.println(); MyContext context2 = new MyContext(); context2.contextInterface(); StrategyAspectB.aspectOf(context2).activate(); context2.contextInterface(); StrategyAspectA.aspectOf(context2).activate(); context2.contextInterface(); } }実行結果:
MyContext.contextInterface() StrategyAspectA.myAlgorithmInterface() - app.StrategyAspectA@e48e1b StrategyAspectB.myAlgorithmInterface() - app.StrategyAspectB@12dacd1 MyContext.contextInterface() StrategyAspectB.myAlgorithmInterface() - app.StrategyAspectB@42719c StrategyAspectA.myAlgorithmInterface() - app.StrategyAspectA@30c221
実装 - その 8
段階 - その 1
public class Context { public void contextInterface() { System.out.println("Context.contextInterface()"); } }
public interface Strategy { public void algorithmInterface(); }
public class ConcreteStrategyA implements Strategy { public void algorithmInterface() { System.out.println("ConcreteStrategyA.algorithmInterface()"); } }
public class ConcreteStrategyB implements Strategy { public void algorithmInterface() { System.out.println("ConcreteStrategyB.algorithmInterface()"); } }
public aspect StrategyAspect pertarget( target(Context) ) { private Strategy strategy; void around() : call( void Context.contextInterface() ) { if (strategy != null) { strategy.algorithmInterface(); } else { proceed(); } } public void setStrategy(Strategy strategy) { this.strategy = strategy; } }
public class Client { public static void main(String[] args) { Context context = new Context(); context.contextInterface(); StrategyAspect.aspectOf(context).setStrategy( new ConcreteStrategyA() ); context.contextInterface(); StrategyAspect.aspectOf(context).setStrategy( new ConcreteStrategyB() ); context.contextInterface(); } }実行結果:
Context.contextInterface() ConcreteStrategyA.algorithmInterface() ConcreteStrategyB.algorithmInterface()
段階 - その 2
public class Context { // 変更なし public void contextInterface() { System.out.println("Context.contextInterface()"); } }
public interface Strategy { // 変更なし public void algorithmInterface(); }
public class ConcreteStrategyA implements Strategy { // 変更なし public void algorithmInterface() { System.out.println("ConcreteStrategyA.algorithmInterface()"); } }
public class ConcreteStrategyB implements Strategy { // 変更なし public void algorithmInterface() { System.out.println("ConcreteStrategyB.algorithmInterface()"); } }
import peraspect.PerTarget; import peraspect.PerTargetAspect; public aspect StrategyAspect implements PerTarget { private Strategy strategy; void around() : call( void Context.contextInterface() ) { if (strategy != null) { strategy.algorithmInterface(); } else { proceed(); } } public void setStrategy(Strategy strategy) { this.strategy = strategy; } protected static aspect PerTargetImpl extends PerTargetAspect.Impl { protected pointcut targetObj(Object targetObj) : target(targetObj) && target(Context); protected PerTarget getAspect() { return StrategyAspect.aspectOf(); } } public static StrategyAspect aspectOf(Object obj) { return (StrategyAspect)StrategyAspect.aspectOf().getAspect(obj); } }
public class Client { public static void main(String[] args) { Context context = new Context(); context.contextInterface(); StrategyAspect.aspectOf(context).setStrategy( new ConcreteStrategyA() ); context.contextInterface(); StrategyAspect.aspectOf(context).setStrategy( new ConcreteStrategyB() ); context.contextInterface(); } }実行結果:
Context.contextInterface() ConcreteStrategyA.algorithmInterface() ConcreteStrategyB.algorithmInterface()
実装 - その 9
この実装では、Context の役割を持つ対象として、クラスではなくアスペクトを考えます。
public interface Strategy { public void algorithmInterface(); }
public class ConcreteStrategyA implements Strategy { public void algorithmInterface() { System.out.println("ConcreteStrategyA.algorithmInterface()"); } }
public class ConcreteStrategyB implements Strategy { public void algorithmInterface() { System.out.println("ConcreteStrategyB.algorithmInterface()"); } }
public class Component { public void method() { System.out.println("Component.method()"); } }
public aspect ComponentAspect { private Strategy strategy = new NullStrategy(); before() : call( void Component.method() ) { strategy.algorithmInterface(); } public void setStrategy(Strategy strategy) { this.strategy = strategy; } private static class NullStrategy implements Strategy { public void algorithmInterface() { } } }
public class Client { public static void main(String[] args) { Component comp = new Component(); comp.method(); System.out.println(); ComponentAspect.aspectOf().setStrategy( new ConcreteStrategyA() ); comp.method(); System.out.println(); ComponentAspect.aspectOf().setStrategy( new ConcreteStrategyB() ); comp.method(); System.out.println(); } }実行結果:
Component.method() ConcreteStrategyA.algorithmInterface() Component.method() ConcreteStrategyB.algorithmInterface() Component.method()
使用例 - その 1
import org.aspectj.lang.JoinPoint; public interface LoggingStrategy { public void log(JoinPoint jp); }
import org.aspectj.lang.JoinPoint; public class SimpleLogging implements LoggingStrategy { public void log(JoinPoint jp) { System.out.println("SimpleLogging"); } }
import org.aspectj.lang.JoinPoint; public class NormalLogging implements LoggingStrategy { public void log(JoinPoint jp) { System.out.println("NormalLogging"); // jp 使ってロギングとか } }
import org.aspectj.lang.JoinPoint; public aspect LoggingAspect { private LoggingStrategy strategy = new NullLoggingStrategy(); before() : call( void Component.method() ) { strategy.log(thisJoinPoint); } public void setLoggingStrategy(LoggingStrategy strategy) { this.strategy = strategy; } private static class NullLoggingStrategy implements LoggingStrategy { public void log(JoinPoint jp) { } } }
public class Client { public static void main(String[] args) { Component comp = new Component(); comp.method(); System.out.println(); LoggingAspect.aspectOf().setLoggingStrategy( new SimpleLogging() ); comp.method(); System.out.println(); LoggingAspect.aspectOf().setLoggingStrategy( new NormalLogging() ); comp.method(); System.out.println(); } }実行結果:
Component.method() SimpleLogging Component.method() NormalLogging Component.method()
参考文献とリソース
更新履歴
todo