最終更新日 : 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