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

最終更新日 : 2003/5/26 (2003/5/15 より)

実装 - その 1

段階 - その 1

(1.1rc2 OK)

public interface Component {
	public void operation();
}
public class ComponentCore implements Component {
	public void operation() {
		System.out.println("operation");
	}
}
public aspect RoleAspect {

	public void Component.addRole(RoleType type) { }
}
public class RoleType {
	protected RoleType() { }
}
public aspect ConcreteRoleA implements Component perthis( addRole(ComponentCore) )  {

	protected static class RoleA extends RoleType { };

	private pointcut addRole(ComponentCore core) :
		this(core) &&
		args(RoleA) &&
		execution( void Component.addRole(RoleType) ) ;

	private ComponentCore core;

	public static final RoleType RoleType.ROLE_A = new RoleA();

	after(ComponentCore core) : addRole(core) {
		this.core = core;
	}

	public static ConcreteRoleA getInstance(Component comp) {

		if ( ConcreteRoleA.hasAspect(comp) ) {
			return ConcreteRoleA.aspectOf(comp);
		} else {
			return null;
		}
	}
	
	public void operation() {
		core.operation();
	}
	public void addedBehavior() {
		System.out.println("addedBehavior()");
	}
}
public class Client {

	public static void main(String[] args) throws Exception {

		Component comp = new ComponentCore();

		comp.operation(); // operation


		System.out.println( ConcreteRoleA.getInstance(comp) ); // null


		comp.addRole(RoleType.ROLE_A);

		ConcreteRoleA role = ConcreteRoleA.getInstance(comp);

		role.addedBehavior(); // addedBehavior()


		Component comp2 = role;

		comp2.operation(); // operation
	}
}

段階 - その 2 : 複数の役割

(1.1rc2 OK)

public interface Component {
	// ... 変更なし
}
public class ComponentCore implements Component {
	// ... 変更なし
}
public class RoleType {
	// ... 変更なし
}
public aspect RoleAspect {
	// ... 変更なし
}
// 特に変更なし
public aspect ConcreteRoleA implements Component perthis( addRole(ComponentCore) )  {
	
	protected static class RoleA extends RoleType {};

	private pointcut addRole(ComponentCore core) :
		this(core) &&
		args(RoleA) &&
		execution( void Component.addRole(RoleType) ) ;

	private ComponentCore core;

	public static final RoleType RoleType.ROLE_A = new RoleA();

	after(ComponentCore core) : addRole(core) {
		this.core = core;
	}

	public static ConcreteRoleA getInstance(Component comp) {

		if ( ConcreteRoleA.hasAspect(comp) ) {
			return ConcreteRoleA.aspectOf(comp);
		} else {
			return null;
		}
	}
	
	public void operation() {
		core.operation();
	}
	public void addedBehavior() {
		System.out.println("ConcreteRoleA - addedBehavior");
	}
}
public aspect ConcreteRoleB implements Component perthis( addRole(ComponentCore) )  {

	protected static class RoleB extends RoleType {};

	private pointcut addRole(ComponentCore core) :
		this(core) &&
		args(RoleB) &&
		execution( void Component.addRole(RoleType) ) ;

	private ComponentCore core;

	public static final RoleType RoleType.ROLE_B = new RoleB();

	after(ComponentCore core) : addRole(core) {
		this.core = core;
	}

	public static ConcreteRoleB getInstance(Component comp) {

		if ( ConcreteRoleB.hasAspect(comp) ) {
			return ConcreteRoleB.aspectOf(comp);
		} else {
			return null;
		}
	}
	
	public void operation() {
		core.operation();
	}
	public void addedBehavior() {
		System.out.println("ConcreteRoleB - addedBehavior");
	}
}
public class Client {

	public static void main(String[] args) throws Exception {

		Component comp = new ComponentCore();

		comp.operation(); // operation

		// role A
		System.out.println( ConcreteRoleA.getInstance(comp) ); // null


		comp.addRole(RoleType.ROLE_A);

		ConcreteRoleA roleA = ConcreteRoleA.getInstance(comp);

		roleA.addedBehavior(); // ConcreteRoleA - addedBehavior


		// role B
		System.out.println( ConcreteRoleB.getInstance(comp) ); // null


		comp.addRole(RoleType.ROLE_B);

		ConcreteRoleB roleB = ConcreteRoleB.getInstance(comp);

		roleB.addedBehavior(); // ConcreteRoleB - addedBehavior

		comp = roleB;
		comp.operation(); // operation
	}
}

段階 - その 3 : リファクタリング - 具象役割アスペクト間の共通コードの排除 or 抽象役割アスペクトの導入

(1.1rc2 OK)

public abstract aspect ComponentRole implements Component perthis( addRole(ComponentCore) ) {

	protected ComponentCore core;

	protected abstract pointcut addRole(ComponentCore core);

	after(ComponentCore core) : addRole(core) {
		this.core = core;
	}

	public void operation() {
		core.operation();
	}
}
public aspect ConcreteRoleA extends ComponentRole {

	protected static class RoleA extends RoleType {};

	protected pointcut addRole(ComponentCore core) :
		this(core) &&
		args(RoleA) &&
		execution( void Component.addRole(RoleType) ) ;

	public static final RoleType RoleType.ROLE_A = new RoleA();


	public static ConcreteRoleA getInstance(Component comp) {

		if ( ConcreteRoleA.hasAspect(comp) ) {
			return ConcreteRoleA.aspectOf(comp);
		} else {
			return null;
		}
	}
	public void addedBehavior() {
		System.out.println("ConcreteRoleA - addedBehavior");
	}
}
public aspect ConcreteRoleB extends ComponentRole  {

	protected static class RoleB extends RoleType {};

	protected pointcut addRole(ComponentCore core) :
		this(core) &&
		args(RoleB) &&
		execution( void Component.addRole(RoleType) ) ;

	public static final RoleType RoleType.ROLE_B = new RoleB();

	public static ConcreteRoleB getInstance(Component comp) {

		if ( ConcreteRoleB.hasAspect(comp) ) {
			return ConcreteRoleB.aspectOf(comp);
		} else {
			return null;
		}
	}

	public void addedBehavior() {
		System.out.println("ConcreteRoleB - addedBehavior");
	}
}

段階 - その 3 : リファクタリング - pointcut の引き上げ

(1.1rc2 OK)

public abstract aspect ComponentRole implements Component perthis( addRole(ComponentCore) ) {

	protected ComponentCore core;

	protected abstract pointcut roleType();

	protected pointcut addRole(ComponentCore core) :
		roleType() && 
		this(core) &&
		execution( void Component.addRole(RoleType) ) ;

	after(ComponentCore core) : addRole(core) {
		this.core = core;
	}

	public void operation() {
		core.operation();
	}
}
public aspect ConcreteRoleA extends ComponentRole {

	protected pointcut roleType() : args(RoleA);

	protected static class RoleA extends RoleType {};

	public static final RoleType RoleType.ROLE_A = new RoleA();


	public static ConcreteRoleA getInstance(Component comp) {

		if ( ConcreteRoleA.hasAspect(comp) ) {
			return ConcreteRoleA.aspectOf(comp);
		} else {
			return null;
		}
	}
	public void addedBehavior() {
		System.out.println("ConcreteRoleA - addedBehavior");
	}
}
public aspect ConcreteRoleB extends ComponentRole  {

	protected pointcut roleType() : args(RoleB);

	protected static class RoleB extends RoleType {};

	public static final RoleType RoleType.ROLE_B = new RoleB();

	public static ConcreteRoleB getInstance(Component comp) {

		if ( ConcreteRoleB.hasAspect(comp) ) {
			return ConcreteRoleB.aspectOf(comp);
		} else {
			return null;
		}
	}

	public void addedBehavior() {
		System.out.println("ConcreteRoleB - addedBehavior");
	}
}

段階 - その 4 : リファクタリング - getInstance()

(1.1rc2 OK)

public abstract aspect ComponentRole implements Component perthis( addRole(ComponentCore) ) {

	protected ComponentCore core;

	protected abstract pointcut roleType();

	protected pointcut addRole(ComponentCore core) :
		roleType() && 
		this(core) &&
		execution( void Component.addRole(RoleType) ) ;

	after(ComponentCore core) : addRole(core) {
		this.core = core;
	}

	public void operation() {
		core.operation();
	}

	private static aspect Impl {

		Object around(Component comp) :
			args(comp) && call(* ComponentRole+.getInstance(Component) )
		{
			Class roleType = thisJoinPoint.getSignature().getDeclaringType();
			Class[] paramTypes = new Class[] { Object.class };

			try {
				Method m = 
					roleType.getDeclaredMethod("aspectOf", paramTypes);

				return m.invoke(null, new Object[] { comp });

			} catch (Exception e) { }

			return null;
		}
	}
}
public aspect ConcreteRoleA extends ComponentRole {

	protected static class RoleA extends RoleType {};

	protected pointcut roleType() : args(RoleA);

	public static final RoleType RoleType.ROLE_A = new RoleA();


	public static ConcreteRoleA getInstance(Component comp) {
		return null;
	}

	public void addedBehavior() {
		System.out.println("ConcreteRoleA - addedBehavior");
	}
}
public aspect ConcreteRoleB extends ComponentRole  {

	protected static class RoleB extends RoleType {};

	protected pointcut roleType() : args(RoleB);

	public static final RoleType RoleType.ROLE_B = new RoleB();

	public static ConcreteRoleB getInstance(Component comp) {
		return null;
	}

	public void addedBehavior() {
		System.out.println("ConcreteRoleB - addedBehavior");
	}
}

段階 - その 5 : 役割の削除

(1.1rc2 OK)

public aspect RoleAspect {

	public void Component.addRole(RoleType type) { }
	public void Component.removeRole(RoleType type) { }
}
public abstract aspect ComponentRole implements Component perthis( addRole(ComponentCore) ) {

	// ... 変更なし

	void around() : execution( void Component.removeRole(RoleType) ) {
		core = null;
	}

	private static aspect Checker {

		Object around() : adviceexecution() && within(Impl) {

			Object role = proceed();

			return role == null || toRole(role).core == null ? null : role;
		}

		private ComponentRole toRole(Object role) {
			return null;
		}

		Object around(ComponentRole role) :
			args(role) && execution(ComponentRole Checker.toRole(Object) )
		{
			return role;
		}
	}

	private static aspect Impl {
		// ... 変更なし
	}
}
public class Client {

	public static void main(String[] args) throws Exception {

		Component comp = new ComponentCore();

		ComponentRole role = ConcreteRoleA.getInstance(comp);
		System.out.println( role ); // null

		// 追加
		comp.addRole(RoleType.ROLE_A);

		role = ConcreteRoleA.getInstance(comp);
		System.out.println( role ); // dp.roleobj.ConcreteRoleA@1cfb549

		// 削除
		comp.removeRole(RoleType.ROLE_A);

		role = ConcreteRoleA.getInstance(comp);
		System.out.println( role ); // null

		// 追加
		comp.addRole(RoleType.ROLE_A);

		role = ConcreteRoleA.getInstance(comp);
		System.out.println( role ); // dp.roleobj.ConcreteRoleA@1cfb549
	}
}

段階 - その 6 : 役割オブジェクトを通しての役割の追加

(1.1rc2 OK)

今のままでは:

public class Client {

	public static void main(String[] args) throws Exception {

		Component comp = new ComponentCore();

		comp.addRole(RoleType.ROLE_A);

		ComponentRole role = ConcreteRoleA.getInstance(comp);
		System.out.println( role ); // dp.roleobj.ConcreteRoleA@1034bb5


		role.addRole(RoleType.ROLE_B);

		role = ConcreteRoleB.getInstance(comp);
		System.out.println( role ); // null
	}
}
役割オブジェクトを通してでも新たな役割を追加できるようにする:
public abstract aspect ComponentRole implements Component perthis( addRole(ComponentCore) ) {

	protected ComponentCore core;

	// ... 変更なし

	public void addRole(RoleType type) {
		core.addRole(type);
	}

	public void operation() {
		core.operation();
	}
	// ... 変更なし
}
public class Client {

	public static void main(String[] args) throws Exception {

		Component comp = new ComponentCore();

		comp.addRole(RoleType.ROLE_A);

		ComponentRole role = ConcreteRoleA.getInstance(comp);
		System.out.println( role ); // dp.roleobj.ConcreteRoleA@1034bb5


		role.addRole(RoleType.ROLE_B);

		role = ConcreteRoleB.getInstance(comp);
		System.out.println( role ); // dp.roleobj.ConcreteRoleB@15f5897
	}
}

段階 - その 7 : 役割オブジェクトを通しての役割の削除

(1.1rc2 OK)

public abstract aspect ComponentRole implements Component perthis( addRole(ComponentCore) ) {

	// 前と一緒

	void around() : roleType() && execution( void Component.removeRole(RoleType) ) {
		core = null;
	}

	public void addRole(RoleType type) {
		core.addRole(type);
	}

	public void removeRole(RoleType type) {
		core.removeRole(type);
	}

	public void operation() {
		core.operation();
	}
	// ... 前と一緒
}
public class Client {

	public static void main(String[] args) throws Exception {

		Component comp = new ComponentCore();

		// 追加
		comp.addRole(RoleType.ROLE_A);

		ComponentRole role = ConcreteRoleA.getInstance(comp);
		System.out.println( role ); // dp.roleobj.ConcreteRoleA@b162d5


		// 追加
		comp.addRole(RoleType.ROLE_B);

		role = ConcreteRoleB.getInstance(comp);
		System.out.println( role ); // dp.roleobj.ConcreteRoleB@1cfb549


		// 削除
		role.removeRole(RoleType.ROLE_A);
		role.removeRole(RoleType.ROLE_B);


		// チェック
		role = ConcreteRoleA.getInstance(comp);
		System.out.println( role ); // null

		role = ConcreteRoleB.getInstance(comp);
		System.out.println( role ); // null
	}
}

段階 - その 8 : 役割オブジェクトを通しての役割オブジェクトの取得

(1.1rc2 OK)

今のままでは:

public class Client {

	public static void main(String[] args) throws Exception {

		Component comp = new ComponentCore();

		comp.addRole(RoleType.ROLE_A);
		comp.addRole(RoleType.ROLE_B);

		ComponentRole role = ConcreteRoleA.getInstance(comp);
		System.out.println( role );

		role = ConcreteRoleB.getInstance(role);
		System.out.println( role ); // null
	}
}
public abstract aspect ComponentRole implements Component perthis( addRole(ComponentCore) ) {
	
	// ... 前と一緒


	private static aspect Impl {

		private pointcut getInstance() :
			call(* ComponentRole+.getInstance(Component) );

		Object around(ComponentCore core) : args(core) && getInstance() {

			return getRoleInstance(thisJoinPoint, core);
		}

		Object around(ComponentRole role) : args(role) && getInstance() {

			return getRoleInstance(thisJoinPoint, role.core);
		}

		private Object getRoleInstance(JoinPoint jp, ComponentCore core) {

			// 以下は前と一緒
			Class roleType = jp.getSignature().getDeclaringType();
			Class[] paramTypes = new Class[] { Object.class };

			try {
				Method m = 
					roleType.getDeclaredMethod("aspectOf", paramTypes);

				return m.invoke(null, new Object[] { core });

			} catch (Exception e) { }
			
			return null;
		}

	}
}

段階 - その 9 : hasRole

(1.1rc2 OK)

public aspect RoleAspect {

	public void Component.addRole(RoleType type) { }
	public void Component.removeRole(RoleType type) { }
	public boolean Component.hasRole(RoleType type) { return false; }
}
public abstract aspect ComponentRole implements Component perthis( addRole(ComponentCore) ) {

	// ... 前と一緒

	after(ComponentCore core) : addRole(core) {
		this.core = core;
	}

	void around() : roleType() && execution( void Component.removeRole(RoleType) ) {
		core = null;
	}

	boolean around() : roleType() && execution( boolean Component.hasRole(RoleType) ) {
		return core != null;
	}

	public void addRole(RoleType type) {
		core.addRole(type);
	}

	public void removeRole(RoleType type) {
		core.removeRole(type);
	}

	public boolean hasRole(RoleType type) {
		return core.hasRole(type);
	}

	public void operation() {
		core.operation();
	}
	// ... 前と一緒
}
public class Client {

	public static void main(String[] args) throws Exception {

		Component comp = new ComponentCore();

		System.out.println( comp.hasRole(RoleType.ROLE_A) ); // false


		comp.addRole(RoleType.ROLE_A);

		System.out.println( comp.hasRole(RoleType.ROLE_A) ); // true


		ComponentRole role = ConcreteRoleA.getInstance(comp);


		System.out.println( role.hasRole(RoleType.ROLE_A) ); // true
		System.out.println( role.hasRole(RoleType.ROLE_B) ); // false
	}
}

段階 - その 10 : Role Object パターンの一般化 - その 1

(1.1rc2 OK)

public abstract aspect RoleProtocol {

	protected interface RoleProtocolComponent { }
	protected interface RoleProtocolRoleType { }

	protected abstract pointcut roleType();

	protected pointcut addRoleMethodExecution() :
		execution( void RoleProtocolComponent+.addRole(RoleProtocolRoleType+) ) ;

	protected pointcut addRoleExecution() :
		roleType() && addRoleMethodExecution();
}
public abstract aspect ComponentRole extends RoleProtocol implements Component perthis( addRole(ComponentCore) ) {

	declare parents: Component implements RoleProtocolComponent;
	declare parents: RoleType  implements RoleProtocolRoleType;

	protected ComponentCore core;

	protected pointcut addRole(ComponentCore core) :
		this(core) && addRoleExecution();

	// ... 変更なし
}

段階 - その 11 : Role Object パターンの一般化 - その 2

(1.1rc2 OK)

public abstract aspect RoleProtocol perthis( addRoleExecution() ) {

	protected interface RoleProtocolComponent { }
	protected interface RoleProtocolComponentCore { }
	protected interface RoleProtocolRoleType { }

	// ... 変更なし
}
public abstract aspect ComponentRole extends RoleProtocol implements Component  {

	declare parents: Component     implements RoleProtocolComponent;
	declare parents: ComponentCore implements RoleProtocolComponentCore;
	declare parents: RoleType      implements RoleProtocolRoleType;
}

段階 - その 12 : Role Object パターンの一般化 - その 3 : 少しリファクタリング

(1.1rc2 OK)

public abstract aspect RoleProtocol perthis( addRole() ) {

	// ... 変更なし

	protected pointcut addRole() :
		roleType() && addRoleMethodExecution();
}
public abstract aspect ComponentRole extends RoleProtocol implements Component  {

	// ... 変更なし

	after(ComponentCore core) : this(core) && addRole() {
		this.core = core;
	}
	// ... 変更なし
}

段階 - その 13 : Role Object パターンの一般化 - その 4 :

(1.1rc2 OK)

public abstract aspect RoleProtocol perthis( addRole() ) {

	// ... 変更なし

	protected abstract RoleProtocolComponentCore getCore();

	protected static aspect Impl {

		private pointcut getInstance() :
			call(* RoleProtocol+.getInstance(RoleProtocolComponent+) );

		Object around(RoleProtocolComponentCore core) : args(core) && getInstance() {

			return getRoleInstance(thisJoinPoint, core);
		}

		Object around(RoleProtocol role) : args(role) && getInstance() {

			return getRoleInstance(thisJoinPoint, role.getCore() );
		}

		private Object getRoleInstance(JoinPoint jp, RoleProtocolComponentCore core) {

			// 以下は変更なし
			Class roleType = jp.getSignature().getDeclaringType();
			Class[] paramTypes = new Class[] { Object.class };

			try {
				Method m = 
					roleType.getDeclaredMethod("aspectOf", paramTypes);

				return m.invoke(null, new Object[] { core });

			} catch (Exception e) { }
			
			return null;
		}
	}
}
public abstract aspect ComponentRole extends RoleProtocol implements Component  {

	// ... 変更なし

	protected RoleProtocolComponentCore getCore() {
		return core;
	}
	
	// ... インナー Impl クラスがなくなった以外変更なし
}

段階 - その 14 : Role Object パターンの一般化 - その 5 : Checker の引き上げ

(1.1rc2 OK)

public abstract aspect RoleProtocol perthis( addRole() ) {

	// ... 変更なし

	private static aspect Checker {

		Object around() : adviceexecution() && within(Impl) {

			Object role = proceed();

			return role == null || toRole(role).getCore() == null ? null : role;
		}

		private RoleProtocol toRole(Object role) {
			return null;
		}

		Object around(RoleProtocol role) :
			args(role) && execution(RoleProtocol Checker.toRole(Object)) 
		{
			return role;
		}
	}

	protected static aspect Impl { // ... 変更なし
	}
}
public abstract aspect ComponentRole extends RoleProtocol implements Component  {
	// ... Checker クラスが引き上げられた以外変更なし
}

段階 - その 15 : Role Object パターンの一般化 - その 6

(1.1rc2 OK)

public abstract aspect RoleProtocol perthis( addRole() ) {

	// ... 変更なし

	private RoleProtocolComponentCore core;


	protected void setCore(RoleProtocolComponentCore core) {
		this.core = core;
	}


	// ... 変更なし

	void around() :
		roleType() && execution( void RoleProtocolComponent+.removeRole(RoleProtocolRoleType+) )
	{
		core = null;
	}

	boolean around() :
		roleType() && execution( boolean RoleProtocolComponent+.hasRole(RoleProtocolRoleType+) )
	{
		return core != null;
	}
	// ... 変更なし
}
public abstract aspect ComponentRole extends RoleProtocol implements Component  {
	// ... 変更なし

	after(ComponentCore core) : this(core) && addRole() {
		setCore(core);
		this.core = core;
	}
	// ... 変更なし
}

段階 - その 16 : Role Object パターンの一般化 - その 7 : 名前の修正

(1.1rc2 OK)

public abstract aspect RoleProtocol perthis( addRole() ) {

	protected interface Component { }
	protected interface ComponentCore { }
	protected interface RoleType { }

	private ComponentCore core;

	protected abstract ComponentCore getCore();

	protected void setCore(ComponentCore core) {
		this.core = core;
	}

	protected abstract pointcut roleType();

	protected pointcut addRoleMethodExecution() :
		execution( void Component+.addRole(RoleType+) ) ;

	protected pointcut addRole() :
		roleType() && addRoleMethodExecution();

	void around() :
		roleType() && execution( void Component+.removeRole(RoleType+) )
	{
		core = null;
	}

	boolean around() :
		roleType() && execution( boolean Component+.hasRole(RoleType+) )
	{
		return core != null;
	}

	private static aspect Checker {

		Object around() : adviceexecution() && within(Impl) {

			Object role = proceed();

			return role == null || toRole(role).getCore() == null ? null : role;
		}

		private RoleProtocol toRole(Object role) {
			return null;
		}

		Object around(RoleProtocol role) :
			args(role) && execution(RoleProtocol Checker.toRole(Object))
		{
			return role;
		}
	}

	protected static aspect Impl {

		private pointcut getInstance() :
			call(* RoleProtocol+.getInstance(Component+) );

		Object around(ComponentCore core) : args(core) && getInstance() {

			return getRoleInstance(thisJoinPoint, core);
		}

		Object around(RoleProtocol role) : args(role) && getInstance() {

			return getRoleInstance(thisJoinPoint, role.getCore());
		}

		private Object getRoleInstance(JoinPoint jp, ComponentCore core) {

			Class roleType = jp.getSignature().getDeclaringType();
			Class[] paramTypes = new Class[] { Object.class };

			try {
				Method m = 
					roleType.getDeclaredMethod("aspectOf", paramTypes);

				return m.invoke(null, new Object[] { core });

			} catch (Exception e) { }

			return null;
		}
	}
}
public abstract aspect StringComponentRole extends RoleProtocol implements StringComponent  {

	declare parents: StringComponent         implements Component;
	declare parents: StringComponentCore     implements ComponentCore;
	declare parents: StringComponentRoleType implements RoleType;

	protected StringComponentCore core;

	protected ComponentCore getCore() {
		return core;
	}

	after(StringComponentCore core) : this(core) && addRole() {
		setCore(core);
		this.core = core;
	}

	public void addRole(StringComponentRoleType type) {
		core.addRole(type);
	}

	public void removeRole(StringComponentRoleType type) {
		core.removeRole(type);
	}

	public boolean hasRole(StringComponentRoleType type) {
		return core.hasRole(type);
	}

	public void operation() {
		core.operation();
	}
}
public class Client {

	public static void main(String[] args) throws Exception {

		StringComponent comp = new StringComponentCore();

		comp.addRole(StringComponentRoleType.ROLE_A);

		System.out.println( ConcreteRoleA.getInstance(comp) );
	}
}

ソースコード

参考文献とリソース

参考文献: リソース:

更新履歴

todo

[
戻る ]