AspectJ を使ったデザインパターンの改善と支援 >
Abstract Factory

asato <asato@ncfreak.com>

最終更新日 : 2004/3/1 (2002/9/26 より)

テスト環境

Abstract Factory

お互いに関連したり依存し合うオブジェクト群を、その具象クラスを明確にせずに生成するためのインタフェースを提供する。

考慮点

実装に関するもの: 結果に関するもの:

AspectJ を使った Abstract Factory に関するテクニックの種類

Abstract Factory の導入

意図: Abstract Factory パターンの候補となりうるコードに、Abstract Factory パターンを導入する。

適用可能性:

結果:

  1. 必ずしも、具象クラスは局所化されるわけではない: Abstract Factory パターンの結果の 1 つに「Client オブジェクトは、各インスタンスを抽象インタフェースを通して操作する」と書かれているが、このテクニック ("Abstract Factory の導入" のこと) では、必ずしもクライアントが扱うインスタンスが抽象インタフェースを通して操作するとは限らない。

保持されるもの:

手順:
  1. 本当にソースコードを直接変更できない理由があるかどうかを考える。
    • 変更できるなら -- リファクタリングを行う。

サンプルコード:

package dp.af;

public class ProductA {
	public void method() {
		System.out.println("ProductA");
	}
}
package dp.af;

public class ProductB {
	public void method() {
		System.out.println("ProductB");
	}
}
package dp.af;

public class SomeClass {
	public void method() {
		ProductA productA = new ProductA();
		ProductB productB = new ProductB();

		productA.method();
		productB.method();
	}
}
package dp.af;

public interface AbstractFactory {
	public ProductA createProductA();
	public ProductB createProductB();
}
package dp.af;

public class ConcreteFactory implements AbstractFactory {
	public ProductA createProductA() {
		return new SubProductA();
	}
	public ProductB createProductB() {
		return new SubProductB();
	}
}
package dp.af;

public class SubProductA extends ProductA {
	public void method() {
		System.out.println("SubProductA");
	}
}
package dp.af;

public class SubProductB extends ProductB {
	public void method() {
		System.out.println("SubProductB");
	}
}
package dp;

import dp.af.*;

public class Client {

	public static void main(String[] args) {

		AbstractFactory fact = new ConcreteFactory();

		new SomeClass().method(fact);
	}
}
package dp.af;

public aspect AbstractFactoryAspect {

	public void SomeClass.method(AbstractFactory fact) {
		method();
	}

	pointcut clientMethod(AbstractFactory fact) :
		args(fact) && call( void SomeClass.method(AbstractFactory) );

	pointcut newProductA(AbstractFactory fact) :
		call( ProductA.new() ) && cflow( clientMethod(fact) );

	pointcut newProductB(AbstractFactory fact) :
		call( ProductB.new() ) && cflow( clientMethod(fact) );


	ProductA around (AbstractFactory fact) : newProductA(fact) {
		return fact.createProductA();
	}

	ProductB around (AbstractFactory fact) : newProductB(fact) {
		return fact.createProductB();
	}
}
SubProductA
SubProductB

Introduction 使用による新たな種類の部品の追加

新たな種類の部品に対応できるように Abstract Factory パターンを拡張することは容易ではない。なぜならば、AbstractFactory クラスのインタフェースは生成される部品の集合を固定しているからである。新たな種類の部品への対応は、インタフェースの修正が必要になるために、AbstractFactory クラスだけでなくそのすべてのサブクラスを修正しなければならなくなる [GoF, p. 98]。

意図: Introduction を使って新たな種類の部品を生成するメソッドを実装する。

サンプルコード:

package dp.af;

public interface ProductA {
	public void method();
}
package dp.af;

public class ConcreteProductA1 implements ProductA {
	public void method() {
		System.out.println("ConcreteProductA1");
	}
}
package dp.af;

public class ConcreteProductA2 implements ProductA {
	public void method() {
		System.out.println("ConcreteProductA2");
	}
}
package dp.af;

public interface ProductB {
	public void method();
}
package dp.af;

public class ConcreteProductB1 implements ProductB {
	public void method() {
		System.out.println("ConcreteProductB1");
	}
}
package dp.af;

public class ConcreteProductB2 implements ProductB {
	public void method() {
		System.out.println("ConcreteProductB2");
	}
}
package dp.af;

public interface AbstractFactory {
	public ProductA createProductA();
	public ProductB createProductB();
}
package dp.af;

public class ConcreteFactory1 implements AbstractFactory {
	public ProductA createProductA() {
		return new ConcreteProductA1();
	}
	public ProductB createProductB() {
		return new ConcreteProductB1();
	}
}
package dp.af;

public class ConcreteFactory2 implements AbstractFactory {
	public ProductA createProductA() {
		return new ConcreteProductA2();
	}
	public ProductB createProductB() {
		return new ConcreteProductB2();
	}
}
package dp;

import dp.af.*;

public class Client {

	public static void main(String[] args) {

		AbstractFactory fact = new ConcreteFactory1();

		ProductA productA = fact.createProductA();
		ProductB productB = fact.createProductB();
		ProductC productC = fact.createProductC();

		productA.method();
		productB.method();
		productC.method();
	}
}
package dp.af;

public interface ProductC {
	public void method();
}
package dp.af;

public class ConcreteProductC1 {
	public void method() {
		System.out.println("ConcreteProductC1");
	}
}
package dp.af;

public class ConcreteProductC2 {
	public void method() {
		System.out.println("ConcreteProductC2");
	}
}
package dp.af;

public aspect AbstractFactoryAspect {

	declare parents: ConcreteProductC1 implements ProductC;
	declare parents: ConcreteProductC2 implements ProductC;

	public abstract ProductC AbstractFactory.createProductC();

	public ProductC ConcreteFactory1.createProductC() {
		return new ConcreteProductC1();
	}
	public ProductC ConcreteFactory2.createProductC() {
		return new ConcreteProductC2();
	}
}
ConcreteProductA1
ConcreteProductB1

積極的な Introduction の使用による Abstract Factory の実装

サンプルコード:
package dp.af;

public interface ProductA {
	public void method();
}
package dp.af;

public class ConcreteProductA1  {
	public void method() {
		System.out.println("ConcreteProductA1");
	}
}
package dp.af;

public class ConcreteProductA2 {
	public void method() {
		System.out.println("ConcreteProductA2");
	}
}
package dp.af;

public interface ProductB {
	public void method();
}
package dp.af;

public class ConcreteProductB1  {
	public void method() {
		System.out.println("ConcreteProductB1");
	}
}
package dp.af;

public class ConcreteProductB2 {
	public void method() {
		System.out.println("ConcreteProductB2");
	}
}
package dp.af;

public interface AbstractFactory { }
package dp.af;

public class ConcreteFactory1  { }
package dp.af;

public class ConcreteFactory2  { }
package dp;

import dp.af.*;

public class Client {

	public static void main(String[] args) {

		AbstractFactory fact = new ConcreteFactory1();

		ProductA productA = fact.createProductA();
		ProductB productB = fact.createProductB();

		productA.method();
		productB.method();
	}
}
package dp.af;

public aspect AbstractFactoryAspect {

	declare parents: ConcreteFactory1 implements AbstractFactory;
	declare parents: ConcreteFactory2 implements AbstractFactory;

	declare parents: ConcreteProductA1 implements ProductA;
	declare parents: ConcreteProductA2 implements ProductA;

	declare parents: ConcreteProductB1 implements ProductB;
	declare parents: ConcreteProductB2 implements ProductB;


	public abstract ProductA AbstractFactory.createProductA();
	public abstract ProductB AbstractFactory.createProductB();

	public ProductA ConcreteFactory1.createProductA() {
		return new ConcreteProductA1();
	}
	public ProductB ConcreteFactory1.createProductB() {
		return new ConcreteProductB1();
	}

	public ProductA ConcreteFactory2.createProductA() {
		return new ConcreteProductA2();
	}
	public ProductB ConcreteFactory2.createProductB() {
		return new ConcreteProductB2();
	}
}
ConcreteProductA1
ConcreteProductB1

実装:

実装 - その 4

GoF によると (p.98):
4.新たな種類の部品に対応することが困難である。 新たな種類の部品に対応できるように Abstract Factory パターンを拡張することは容易ではない。なぜならば、AbstractFactory クラスのインタフェースは生成される部品の集合を固定しているからである。新たな種類の部品への対応は、インタフェースの修正が必要になるために、AbstractFactory クラスだけでなくそのすべてのサブクラスを修正しなければならなくなる。

サンプルコード

ライブラリ側 (dp.lib パッケージ):
package dp.lib;

public interface ProductA { }
package dp.lib;

public interface ProductB { }
package dp.lib;

public class ConcreteProductA implements ProductA { }
package dp.lib;

public class ConcreteProductB implements ProductB { }
package dp.lib;

public interface AbstractFactory {
	public ProductA createProductA();
	public ProductB createProductB();
}
package dp.lib;

public class ConcreteFactory implements AbstractFactory {

	public ProductA createProductA() {
		return new ConcreteProductA();
	}
	
	public ProductB createProductB() {
		return new ConcreteProductB();
	}
}
package dp.lib;

public class Main { // 単に動作確認用
	public static void main(String[] args) {

		AbstractFactory fact = new ConcreteFactory();
	
		System.out.println( fact.createProductA() );
		System.out.println( fact.createProductB() );
	}
}
実行結果:
dp.lib.ConcreteProductA@360be0
dp.lib.ConcreteProductB@192d342
アプリケーション側 (dp.app パッケージ):
package dp.app;

public interface ProductC { }
package dp.app;

public class ConcreteProductC implements ProductC { }
package dp.app;

import dp.lib.AbstractFactory;
import dp.lib.ConcreteFactory;

public aspect AbstractFactoryAspect {

	public abstract ProductC AbstractFactory.createProductC();

	public ProductC ConcreteFactory.createProductC() {
		return new ConcreteProductC();
	}
}
package dp.app;

import dp.lib.AbstractFactory;
import dp.lib.ConcreteFactory;

public class Main {
	public static void main(String[] args) {
		AbstractFactory fact = new ConcreteFactory();
	
		System.out.println( fact.createProductA() );
		System.out.println( fact.createProductB() );
		System.out.println( fact.createProductC() );
	}
}
実行結果:
dp.lib.ConcreteProductA@1ddebc3
dp.lib.ConcreteProductB@194ca6c
dp.app.ConcreteProductC@9931f5

実装 - その 5

public interface ProductA { }
public interface ProductB { }
public class ConcreteProductA implements ProductA { }
public class ConcreteProductB implements ProductB { }
public class MyConcreteProductA implements ProductA { }
public class MyConcreteProductB implements ProductB { }
public class AbstractFactory {
	public ProductA createProductA() {
		return new ConcreteProductA();
	}
	public ProductB createProductB() {
		return new ConcreteProductB();
	}
}
public aspect MyAbstractFactoryAspect {
	
	private boolean isActive;
	
	public static void activate() {
		MyAbstractFactoryAspect.aspectOf().isActive = true;
	}
	
	private pointcut isActive() :
		if (MyAbstractFactoryAspect.aspectOf().isActive);
	
	ProductA around() :
		call(ProductA AbstractFactory.createProductA() ) && isActive()
	{
		return new MyConcreteProductA();
	}

	ProductB around() :
		call(ProductB AbstractFactory.createProductB() ) && isActive()
	{
		return new MyConcreteProductB();
	}
}
public class Client {

	public static void main(String[] args) {

		AbstractFactory fact = new AbstractFactory();
	
		System.out.println( fact.createProductA() );
		System.out.println( fact.createProductB() );

		MyAbstractFactoryAspect.activate();

		System.out.println( fact.createProductA() );
		System.out.println( fact.createProductB() );
	}
}
実行結果:
dp.af.ConcreteProductA@1f33675
dp.af.ConcreteProductB@1690726
dp.af.MyConcreteProductA@9931f5
dp.af.MyConcreteProductB@1f1fba0

新しい ConcreteFactory (or AbstractFactoryAspect) が増えた場合は?

public class YourConcreteProductA implements ProductA { }
public class YourConcreteProductB implements ProductB { }
public aspect YourAbstractFactoryAspect {
	
	private boolean isActive;
	
	public static void activate() {
		YourAbstractFactoryAspect.aspectOf().isActive = true;
	}
	
	private pointcut isActive() :
		if (YourAbstractFactoryAspect.aspectOf().isActive);
	
	ProductA around() :
		call(ProductA AbstractFactory.createProductA() ) && isActive()
	{
		return new YourConcreteProductA();
	}

	ProductB around() :
		call(ProductB AbstractFactory.createProductB() ) && isActive()
	{
		return new YourConcreteProductB();
	}
}
privileged public aspect AbstractFactoryAspectManager {

	after() : call( void YourAbstractFactoryAspect.activate() )  {
		MyAbstractFactoryAspect.aspectOf().isActive = false;
	}
	after() : call( void MyAbstractFactoryAspect.activate() )  {
		YourAbstractFactoryAspect.aspectOf().isActive = false;
	}
}
public class Client {

	public static void main(String[] args) {

		AbstractFactory fact = new AbstractFactory();
	
		System.out.println( fact.createProductA() );
		System.out.println( fact.createProductB() );
		

		MyAbstractFactoryAspect.activate();

		System.out.println( fact.createProductA() );
		System.out.println( fact.createProductB() );


		YourAbstractFactoryAspect.activate();

		System.out.println( fact.createProductA() );
		System.out.println( fact.createProductB() );


		MyAbstractFactoryAspect.activate();

		System.out.println( fact.createProductA() );
		System.out.println( fact.createProductB() );
	}
}
実行結果:
dp.af.ConcreteProductA@7c6768
dp.af.ConcreteProductB@5483cd
dp.af.MyConcreteProductA@1f1fba0
dp.af.MyConcreteProductB@13c5982
dp.af.YourConcreteProductA@14b7453
dp.af.YourConcreteProductB@1d5550d
dp.af.MyConcreteProductA@c2ea3f
dp.af.MyConcreteProductB@a0dcd9

実装 - その 6

public interface ProductA { }
public interface ProductB { }
public class ConcreteProductA implements ProductA { }
public class ConcreteProductB implements ProductB { }
public class AbstractFactory {

	public ProductA createProductA() {
		return new ConcreteProductA();
	}

	public ProductB createProductB() {
		return new ConcreteProductB();
	}
}
public aspect AbstractFactoryAspect pertarget( target(AbstractFactory) ) {

	private boolean isActive;

	public void activate() {
		this.isActive = true;
	}

	public void deactivate() {
		this.isActive = false;
	}

	ProductA around() : call( ProductA AbstractFactory.createProductA() ) {

		if (isActive) {
			return new MyConcreteProductA();

		} else {
			return proceed();
		}
		
	}

	ProductB around() : call( ProductB AbstractFactory.createProductB() ) {

		if (isActive) {
			return new MyConcreteProductB();

		} else {
			return proceed();
		}
		
	}

	private static class MyConcreteProductA implements ProductA { }
	private static class MyConcreteProductB implements ProductB { }
}
public class Client {

	public static void main(String[] args) {

		AbstractFactory fact = new AbstractFactory();
	
		System.out.println( fact.createProductA() );
		System.out.println( fact.createProductB() );
		

		AbstractFactoryAspect.aspectOf(fact).activate();

		System.out.println( fact.createProductA() );
		System.out.println( fact.createProductB() );


		AbstractFactoryAspect.aspectOf(fact).deactivate();

		System.out.println( fact.createProductA() );
		System.out.println( fact.createProductB() );
	}
}
実行結果:
dp.af.ConcreteProductA@7c6768
dp.af.ConcreteProductB@5483cd
dp.af.AbstractFactoryAspect$MyConcreteProductA@19ee1ac
dp.af.AbstractFactoryAspect$MyConcreteProductB@1befab0
dp.af.ConcreteProductA@13c5982
dp.af.ConcreteProductB@1186fab

実装 - その 7

public interface ProductA { }
public interface ProductB { }
public class AbstractFactory {

	public ProductA createProductA() {
		return new DefaultProductA();
	}

	public ProductB createProductB() {
		return new DefaultProductB();
	}

	private static class DefaultProductA implements ProductA { }
	private static class DefaultProductB implements ProductB { }
}
public interface Deployable {

	public static aspect Impl {
		
		private boolean Deployable.isActive;
		
		public void Deployable.activate() {
			this.isActive = true;
		}
		public void Deployable.deactivate() {
			this.isActive = false;
		}
		
		public boolean Deployable.isActive() {
			return isActive;
		}
	}
}
public interface Deployer {

	public void deploy(Deployable deployable);

	public static aspect Impl {

		void around(Deployable deployable) :
			args(deployable) &&
			call(void Deployer.deploy(Deployable)) &&
			if (deployable != null)
		{
			deployable.activate();
			proceed(deployable);
			deployable.deactivate();
		}
	}
}
public aspect AbstractFactoryAspect implements Deployable {

	private pointcut isActive() :
		if ( AbstractFactoryAspect.aspectOf().isActive() );


	private static aspect Impl percflow( execution(void Deployer.deploy(Deployable)) && isActive() )  {
	
		ProductA around() : call( ProductA AbstractFactory.createProductA() ) {
			return new ConcreteProductA();
		}

		ProductB around() : call( ProductB AbstractFactory.createProductB() ) {
			return new ConcreteProductB();
		}
	}

	
	private static class ConcreteProductA implements ProductA { }
	private static class ConcreteProductB implements ProductB { }
}
public class Client {

	public static void main(String[] args) {

		final AbstractFactory fact = new AbstractFactory();
	
		System.out.println( fact.createProductA() );
		System.out.println( fact.createProductB() );
	
		Deployer deployer = new Deployer() {

			public void deploy(Deployable deployable) {
				System.out.println( fact.createProductA() );
				System.out.println( fact.createProductB() );
			}
		};
		
		deployer.deploy( AbstractFactoryAspect.aspectOf() );
	}
}
実行結果:
dp.af.AbstractFactory$DefaultProductA@9931f5
dp.af.AbstractFactory$DefaultProductB@1f1fba0
dp.af.AbstractFactoryAspect$ConcreteProductA@c2ea3f
dp.af.AbstractFactoryAspect$ConcreteProductB@1034bb5

使用例 - その 1

public interface Monster { } // ProductA
public interface Soldier { } // ProductB
public class EnemyFactory { // AbstractFactory

	public Monster createMonster() {
		return new DefaultMonster();
	}

	public Soldier createSoldier() {
		return new DefaultSoldier();
	}

	private static class DefaultMonster implements Monster {}
	private static class DefaultSoldier implements Soldier {}
}
public interface Deployable {

	public static aspect Impl {
		
		private boolean Deployable.isActive;
		
		public void Deployable.activate() {
			this.isActive = true;
		}
		public void Deployable.deactivate() {
			this.isActive = false;
		}
		
		public boolean Deployable.isActive() {
			return isActive;
		}
	}
}
public interface Deployer {

	public void deploy(Deployable deployable);

	public static aspect Impl {

		void around(Deployable deployable) :
			args(deployable) &&
			call(void Deployer.deploy(Deployable)) &&
			if (deployable != null)
		{
			deployable.activate();
			proceed(deployable);
			deployable.deactivate();
		}
	}
}
public aspect EasyModeAspect implements Deployable  {

	private pointcut isActive() : if ( EasyModeAspect.aspectOf().isActive() );
	

	private static aspect Impl percflow( execution(void Deployer.deploy(Deployable)) && isActive() )  {
	
		Monster around() : call( Monster EnemyFactory.createMonster() ) {
			return new EasyModeMonster();
		}

		Soldier around() : call( Soldier EnemyFactory.createSoldier() ) {
			return new EasyModeSoldier();
		}
	}

	
	private static class EasyModeMonster implements Monster {}
	private static class EasyModeSoldier implements Soldier {}
}
public aspect HardModeAspect implements Deployable  {

	private pointcut isActive() : if ( HardModeAspect.aspectOf().isActive() );

	private static aspect Impl percflow( execution(void Deployer.deploy(Deployable)) && isActive() )  {


		Monster around() : call( Monster EnemyFactory.createMonster() ) {
			return new HardModeMonster();
		}

		Soldier around() : call( Soldier EnemyFactory.createSoldier() ) {
			return new HardModeSoldier();
		}
	}

	
	private static class HardModeMonster implements Monster {}
	private static class HardModeSoldier implements Soldier {}
}
public class Client {

	public static void main(String[] args) {

		Deployer deployer = new Deployer() {

			public void deploy(Deployable deployable) {
				gameMain();
			}
		};

		deployer.deploy( getGameModeAspect("easy") );
		deployer.deploy( getGameModeAspect("hard") );
		deployer.deploy( getGameModeAspect(null)   );
	}
	
	public static void gameMain() {
		
		EnemyFactory fact = new EnemyFactory();
		
		System.out.println( fact.createMonster() );
		System.out.println( fact.createSoldier() );
	}
	
	public static Deployable getGameModeAspect(String mode) {

		if (mode == null) return null;

		if ( mode.equals("easy") ) {
			return EasyModeAspect.aspectOf();
		}
		if ( mode.equals("hard") ) {
			return HardModeAspect.aspectOf();
		}
		
		return null;
	}
}
実行結果:
dp.af.EasyModeAspect$EasyModeMonster@187aeca
dp.af.EasyModeAspect$EasyModeSoldier@12dacd1
dp.af.HardModeAspect$HardModeMonster@42719c
dp.af.HardModeAspect$HardModeSoldier@119298d
dp.af.EnemyFactory$DefaultMonster@1e5e2c3
dp.af.EnemyFactory$DefaultSoldier@1fc4bec

使用例 - その 2

基本的には「使用例 - その 1」と同じ。
public interface Monster { } // ProductA
public interface Soldier { } // ProductB
public class EnemyFactory { // AbstractFactory

	public Monster createMonster() {
		return new DefaultMonster();
	}

	public Soldier createSoldier() {
		return new DefaultSoldier();
	}

	private static class DefaultMonster implements Monster {}
	private static class DefaultSoldier implements Soldier {}
}
public interface Deployable {

	public static aspect Impl {
		
		private boolean Deployable.isActive;
		
		public void Deployable.activate() {
			this.isActive = true;
		}
		public void Deployable.deactivate() {
			this.isActive = false;
		}
		
		public boolean Deployable.isActive() {
			return isActive;
		}
	}
}
public interface Deployer {

	public void deploy(Deployable deployable);

	public static aspect Impl {

		void around(Deployable deployable) :
			args(deployable) &&
			call(void Deployer.deploy(Deployable)) &&
			if (deployable != null)
		{
			deployable.activate();
			proceed(deployable);
			deployable.deactivate();
		}
	}
}
public aspect EasyModeAspect implements Deployable  {

	private pointcut isActive() : if ( EasyModeAspect.aspectOf().isActive() );
	

	private static aspect Impl percflow( execution(void Deployer.deploy(Deployable)) && isActive() )  {
	
		Monster around() : call( Monster EnemyFactory.createMonster() ) {
			return new EasyModeMonster();
		}

		Soldier around() : call( Soldier EnemyFactory.createSoldier() ) {
			return new EasyModeSoldier();
		}
	}

	
	private static class EasyModeMonster implements Monster {}
	private static class EasyModeSoldier implements Soldier {}
}
public aspect HardModeAspect implements Deployable  {

	private pointcut isActive() : if ( HardModeAspect.aspectOf().isActive() );

	private static aspect Impl percflow( execution(void Deployer.deploy(Deployable)) && isActive() )  {


		Monster around() : call( Monster EnemyFactory.createMonster() ) {
			return new HardModeMonster();
		}

		Soldier around() : call( Soldier EnemyFactory.createSoldier() ) {
			return new HardModeSoldier();
		}
	}

	
	private static class HardModeMonster implements Monster {}
	private static class HardModeSoldier implements Soldier {}
}
public aspect GameModeAspectDeployment {

	void around(final String mode) : args(mode) && call(void Client.gameMain(String) ) {

		Deployer deployer = new Deployer() {

			public void deploy(Deployable deployable) {
				proceed(mode);
			}
		};

		deployer.deploy( getGameModeAspect(mode) );
	}

	private Deployable getGameModeAspect(String mode) {

		if (mode == null) return null;

		if ( mode.equals("easy") ) {
			return EasyModeAspect.aspectOf();
		}
		if ( mode.equals("hard") ) {
			return HardModeAspect.aspectOf();
		}
		
		return null;
	}
}
public class Client {

	public static void main(String[] args) {

		gameMain("easy");
		gameMain("hard");
		gameMain(null);
	}
	
	public static void gameMain(String mode) {

		EnemyFactory fact = new EnemyFactory();

		System.out.println( fact.createMonster() );
		System.out.println( fact.createSoldier() );
	}
}
実行結果:
dp.af.EasyModeAspect$EasyModeMonster@187aeca
dp.af.EasyModeAspect$EasyModeSoldier@12dacd1
dp.af.HardModeAspect$HardModeMonster@42719c
dp.af.HardModeAspect$HardModeSoldier@119298d
dp.af.EnemyFactory$DefaultMonster@1e5e2c3
dp.af.EnemyFactory$DefaultSoldier@1fc4bec

使用例 - その 3 : フレームワーク

fw.jar (fw パッケージ):
public interface Monster { }
public interface Soldier { }
public class EnemyFactory {

	public Monster createMonster() {
		return new DefaultMonster();
	}

	public Soldier createSoldier() {
		return new DefaultSoldier();
	}

	private static class DefaultMonster implements Monster {}
	private static class DefaultSoldier implements Soldier {}
}
public class Main {

	public static void main(String[] args) {


		if (args.length == 0) {
			gameMain(null);
	
		} else {
			gameMain(args[0]);
		}
	}
	
	public static void gameMain(String mode) {
		
		EnemyFactory fact = new EnemyFactory();
		
		System.out.println( fact.createMonster() );
		System.out.println( fact.createSoldier() );
	}
}
実行結果:
>java -cp fw.jar;C:\aspectj1.1\lib\aspectjrt.jar; fw.Main
fw.EnemyFactory$DefaultMonster@26e431
fw.EnemyFactory$DefaultSoldier@1ddebc3
fw-aspect.jar (fw_aspect パッケージ):
public interface Deployable {

	public static aspect Impl {
		
		private boolean Deployable.isActive;
		
		public void Deployable.activate() {
			this.isActive = true;
		}
		public void Deployable.deactivate() {
			this.isActive = false;
		}
		
		public boolean Deployable.isActive() {
			return isActive;
		}
	}
}
public interface Deployer {

	public void deploy(Deployable deployable);

	public static aspect Impl {

		void around(Deployable deployable) :
			args(deployable) &&
			call(void Deployer.deploy(Deployable)) &&
			if (deployable != null)
		{
			deployable.activate();
			proceed(deployable);
			deployable.deactivate();
		}
	}
}
public interface Proceeder {
	public void proceed();
}
import fw.Main;

public abstract aspect AbstractGameModeAspectDeployment {

	void around(final String mode) : args(mode) && call(void Main.gameMain(String) ) {

		Proceeder proceeder = new Proceeder() {

			public void proceed() {
				proceed(mode);
			}
		};

		createDeployer(proceeder).deploy( getGameModeAspect(mode) );
	}

	protected abstract Deployable getGameModeAspect(String mode);
	protected abstract Deployer createDeployer(Proceeder proceeder);
}
fw-ex.jar (fw_ex パッケージ):
import fw.Monster;
import fw.Soldier;
import fw.EnemyFactory;

import fw_aspect.Deployer;
import fw_aspect.Deployable;

public aspect MyGameModeAspect implements Deployable {

	private pointcut isActive() : if ( MyGameModeAspect.aspectOf().isActive() );
	

	private static aspect Impl percflow( execution(void Deployer.deploy(Deployable)) && isActive() )  {
	
		Monster around() : call( Monster EnemyFactory.createMonster() ) {
			return new MyGameModeMonster();
		}

		Soldier around() : call( Soldier EnemyFactory.createSoldier() ) {
			return new MyGameModeSoldier();
		}
	}

	
	private static class MyGameModeMonster implements Monster {}
	private static class MyGameModeSoldier implements Soldier {}
}
import fw_aspect.Proceeder;
import fw_aspect.Deployer;
import fw_aspect.Deployable;
import fw_aspect.AbstractGameModeAspectDeployment;

public aspect MyGameModeAspectDeployment extends AbstractGameModeAspectDeployment {

	protected Deployer createDeployer(Proceeder proceeder) {
		return new DeployerImpl(proceeder);
	}

	private static class DeployerImpl implements Deployer {
	
		private Proceeder proceeder;
	
		public DeployerImpl(Proceeder proceeder) {
			this.proceeder = proceeder;
		}
	
		public void deploy(Deployable deployable) {
			proceeder.proceed();
		}
	}

	protected Deployable getGameModeAspect(String mode) {

		if (mode == null) return null;
		
		if ( mode.equals("my") )
			return MyGameModeAspect.aspectOf();
	
		return null;
	}
}
実行結果:
>java -cp fw-ex.jar;fw-aspect.jar;C:\aspectj1.1\lib\aspectjrt.jar; fw.Main my
fw_ex.MyGameModeAspect$MyGameModeMonster@a0dcd9
fw_ex.MyGameModeAspect$MyGameModeSoldier@15f5897

参考文献とリソース

リソース:

更新履歴

todo

[
戻る ]