最終更新日 : 2003/8/28
asato <asato@ncfreak.com>
オブジェクト Decorator
サンプルコード (実装例 1):
public class StringComponent {
private String str;
public StringComponent(String str) {
this.str = str;
}
public String getString() {
return str;
}
}
public class ConcreteDecoratorA {
public String getString() {
return "[ " + getComponent().getString() + " ]";
}
}
public class ConcreteDecoratorB {
public String getString() {
return "*** " + getComponent().getString() + " ***";
}
}
public class Client {
public static void main(String[] args) {
StringComponent comp = new StringComponent("aaa");
System.out.println( comp.getString() ); // aaa
Decorator.decorate(comp, new ConcreteDecoratorA() );
System.out.println( comp.getString() ); // [ aaa ]
Decorator.decorate(comp, new ConcreteDecoratorB() );
System.out.println( comp.getString() ); // *** [ aaa ] ***
}
}
public class Decorator { }
public aspect DecoratorAspect {
public static void Decorator.decorate(
StringComponent component,
StringComponentAspect.StringComponentDecorator decorator)
{
StringComponentAspect.aspectOf().decorate(component, decorator);
}
}
リスト. DecoratorProtocol (簡単のため、いくつかのメソッド (undecorate, undecorateAll) の実装を省いている)
import java.util.Map;
import java.util.HashMap;
public abstract aspect DecoratorProtocol {
private Map decorationMap = new HashMap();
private Map pairMap = new HashMap();
protected interface Component { }
protected interface Decorator { }
pointcut componentObj(Component component) :
target(component) && !within(Decorator);
protected void decorate(Object component, Object decorator) {
if ( getDecorator(component) == null) {
pairMap.put(decorator, component);
} else {
pairMap.put( decorator, getDecorator(component) );
}
decorationMap.put(component, decorator);
}
protected Object getComponent(Object decorator) {
return pairMap.get(decorator);
}
protected Object getDecorator(Object component) {
return decorationMap.get(component);
}
}
public aspect StringComponentAspect extends DecoratorProtocol {
declare parents : StringComponent implements Component;
declare parents : StringComponentDecorator implements Decorator;
declare parents : StringComponent implements StringComponentInter;
declare parents : StringComponentDecorator implements StringComponentInter;
declare parents : ConcreteDecoratorA implements StringComponentDecorator;
declare parents : ConcreteDecoratorB implements StringComponentDecorator;
protected interface StringComponentInter { }
protected interface StringComponentDecorator { }
public StringComponentInter StringComponentDecorator.getComponent() {
return StringComponentAspect.aspectOf().getComponent( this );
}
public abstract String StringComponentInter.getString();
pointcut decoratedComponent(Component component) :
componentObj(component) && if ( isDecorated(component) );
pointcut getString(Component component) :
decoratedComponent(component) &&
call( String StringComponent.getString() );
Object around(Component component) : getString(component) {
return getDecorator(component).getString();
}
private static boolean isDecorated(Object component) {
return StringComponentAspect.aspectOf().getDecorator(component) != null;
}
private StringComponentInter getComponent(Decorator decorator) {
return (StringComponentInter)super.getComponent(decorator);
}
private StringComponentDecorator getDecorator(Component component) {
return (StringComponentDecorator)super.getDecorator(component);
}
}
サンプルコード (実装例 2):
AspectJ バージョン 1.1beta4 で動作確認
public class Decorator { }
public aspect DecoratorAspect {
public static void Decorator.decorate(
StringComponent component,
StringComponentAspect.StringComponentDecorator decorator)
{
StringComponentAspect.aspectOf(component).decorate(component, decorator);
}
}
public abstract aspect DecoratorProtocol pertarget( componentTarget() ) {
abstract pointcut componentTarget();
declare parents: Decorator implements Component;
protected interface Component { }
protected interface Decorator { }
Component Decorator.component;
Decorator Component.decorator;
boolean Component.isDecorated() {
return decorator != null;
}
protected void decorate(Component component, Decorator decorator) {
if ( component.isDecorated() ) {
decorator.component = component.decorator;
} else {
decorator.component = component;
}
component.decorator = decorator;
}
protected pointcut decoratedComponent(Component component) :
target(component) &&
!within(Decorator) &&
if ( component.isDecorated() );
}
public aspect StringComponentAspect extends DecoratorProtocol {
pointcut componentTarget() : target(StringComponent);
declare parents: StringComponentInter implements Component;
declare parents: StringComponentInter implements Decorator;
declare parents: StringComponent implements StringComponentInter;
declare parents: StringComponentDecorator implements StringComponentInter;
declare parents: ConcreteDecoratorA implements StringComponentDecorator;
declare parents: ConcreteDecoratorB implements StringComponentDecorator;
protected interface StringComponentInter { }
protected interface StringComponentDecorator { }
public abstract String StringComponentInter.getString();
public StringComponentInter StringComponentInter.getComponent() {
return (StringComponentInter)component;
}
pointcut getString(Component component) :
decoratedComponent(component) &&
call( String StringComponent.getString() );
Object around(Component component) : getString(component) {
return getDecorator(component).getString();
}
public void decorate(StringComponent component, StringComponentDecorator decorator) {
super.decorate(component, decorator);
}
private StringComponentDecorator getDecorator(Component component) {
return (StringComponentDecorator)component.decorator;
}
}
実装上の選択肢
StringComponent comp = new StringComponent("aaa");
Decorator.decorate(comp, new ConcreteDecoratorA() );
StringComponent comp = new StringComponent("aaa");
new ConcreteDecoratorA().decorate(comp);
public aspect StringComponentAspect extends DecoratorProtocol {
// ... その他のコード
public StringComponent StringComponentDecorator.decorate(StringComponent component) {
StringComponentAspect.aspectOf(component).decorate(component, this);
return component;
}
// 必要ないため、削除できる。
/*
public void decorate(StringComponent component, StringComponentDecorator decorator) {
super.decorate(component, decorator);
}
*/
// ... その他のコード
StringComponent comp1 = new StringComponent("aaa");
StringComponent comp2 =
new ConcreteDecoratorB().decorate( new ConcreteDecoratorA().decorate(comp1) );
System.out.println(comp1 == comp2); // true
ConcreteDecoratorA.decorate(comp) や Decorator.decorate(comp, ConcreteDecoratorA.class ) なども考えられる。あるいは component 側から見た実装も考えられる: comp.decorate( new ConcreteDecoratorA() ) や comp.decorate(ConcreteDecoratorA.class) など。
実装 - その 3
段階 - その 1
public interface StringComponentInterface {
public String getString();
}
public class StringComponent {
private String str;
public StringComponent(String str) {
this.str = str;
}
public String getString() {
return str;
}
}
public aspect StringComponentDecorator {
declare parents: StringComponent implements StringComponentInterface;
public StringComponentInterface StringComponentInterface.decorator;
String around(StringComponent comp) :
target(comp) &&
call( String StringComponent.getString() ) &&
if (comp.decorator != null) &&
!within(StringComponentInterface+)
{
StringComponentInterface temp = comp.decorator;
StringComponentInterface decorator = comp.decorator;
while(temp != null) {
decorator = temp;
temp = temp.decorator;
}
return decorator.getString();
}
}
public aspect ConcreteDecoratorA {
public static void decorate(StringComponentInterface comp) {
if (comp.decorator != null) {
decorate(comp.decorator);
return;
}
comp.decorator = new ConcreteDecoratorA.Decorator(comp);
}
private static class Decorator implements StringComponentInterface {
private StringComponentInterface comp;
public Decorator(StringComponentInterface comp) {
this.comp = comp;
}
public String getString() {
return "[[[ " + comp.getString() + " ]]]";
}
}
}
public aspect ConcreteDecoratorB {
public static void decorate(StringComponentInterface comp) {
if (comp.decorator != null) {
decorate(comp.decorator);
return;
}
comp.decorator = new ConcreteDecoratorB.Decorator(comp);
}
private static class Decorator implements StringComponentInterface {
private StringComponentInterface comp;
public Decorator(StringComponentInterface comp) {
this.comp = comp;
}
public String getString() {
return "*** " + comp.getString() + " ***";
}
}
}
public class Client {
public static void main(String[] args) {
StringComponent comp = new StringComponent("aaa");
System.out.println( comp.getString() );
ConcreteDecoratorA.decorate(comp);
System.out.println( comp.getString() ); // [[[ aaa ]]]
ConcreteDecoratorB.decorate(comp);
System.out.println( comp.getString() ); // *** [[[ aaa ]]] ***
}
}
段階 - その 2
public class StringComponent {
private String str;
public StringComponent(String str) {
this.str = str;
}
public String getString() {
return str;
}
}
public interface StringComponentInterface {
public String getString();
}
public aspect StringComponentAspect {
declare parents: StringComponent implements StringComponentInterface;
public StringComponentInterface StringComponentInterface.decorator;
String around(StringComponent comp) :
target(comp) &&
call( String StringComponent.getString() )
&& if (comp.decorator != null)
{
StringComponentInterface decorator = comp.decorator;
while(decorator.decorator != null) {
decorator = decorator.decorator;
}
return decorator.getString();
}
}
public abstract class StringComponentDecorator implements StringComponentInterface {
protected StringComponentInterface comp;
protected StringComponentDecorator(StringComponentInterface comp) {
this.comp = comp;
}
public abstract String getString();
}
public class ConcreteDecoratorA extends StringComponentDecorator {
public ConcreteDecoratorA(StringComponentInterface comp) {
super(comp);
}
public static void decorate(StringComponentInterface comp) {
if (comp.decorator != null) {
decorate(comp.decorator);
} else {
comp.decorator = new ConcreteDecoratorA(comp);
}
}
public String getString() {
return "[[[ " + comp.getString() + " ]]]";
}
}
public class ConcreteDecoratorB extends StringComponentDecorator {
public ConcreteDecoratorB(StringComponentInterface comp) {
super(comp);
}
public static void decorate(StringComponentInterface comp) {
if (comp.decorator != null) {
decorate(comp.decorator);
} else{
comp.decorator = new ConcreteDecoratorB(comp);
}
}
public String getString() {
return "*** " + comp.getString() + " ***";
}
}
public class Client {
public static void main(String[] args) {
StringComponent comp = new StringComponent("aaa");
System.out.println( comp.getString() );
ConcreteDecoratorA.decorate(comp);
System.out.println( comp.getString() ); // [[[ aaa ]]]
ConcreteDecoratorB.decorate(comp);
System.out.println( comp.getString() ); // *** [[[ aaa ]]] ***
}
}
段階 - その 3 : メソッドが 1 つ以上の場合
public class StringComponent {
private String str;
public StringComponent(String str) {
this.str = str;
}
public String getString() {
return str;
}
public String getString2() {
return str;
}
}
public interface StringComponentInterface {
public String getString();
public String getString2();
}
public aspect StringComponentAspect {
declare parents: StringComponent implements StringComponentInterface;
public StringComponentInterface StringComponentInterface.decorator;
pointcut component(StringComponent comp) :
target(comp) && if (comp.decorator != null);
String around(StringComponent comp) :
component(comp) && call( String StringComponent.getString() )
{
return getDecorator(comp).getString();
}
String around(StringComponent comp) :
component(comp) && call( String StringComponent.getString2() )
{
return getDecorator(comp).getString2();
}
private StringComponentInterface getDecorator(StringComponent comp) {
StringComponentInterface decorator = comp.decorator;
while(decorator.decorator != null) {
decorator = decorator.decorator;
}
return decorator;
}
}
public abstract class StringComponentDecorator implements StringComponentInterface {
protected StringComponentInterface comp;
protected StringComponentDecorator(StringComponentInterface comp) {
this.comp = comp;
}
public abstract String getString();
public abstract String getString2();
}
public class ConcreteDecoratorA extends StringComponentDecorator {
// ... 前と同じ
public String getString() {
return "[[[ " + comp.getString() + " ]]]";
}
public String getString2() {
return "+++ " + comp.getString2() + " +++";
}
}
public class ConcreteDecoratorB extends StringComponentDecorator {
// ... 前と同じ
public String getString() {
return "*** " + comp.getString() + " ***";
}
public String getString2() {
return "--- " + comp.getString2() + " ---";
}
}
public class Client {
public static void main(String[] args) {
StringComponent comp = new StringComponent("aaa");
System.out.println( comp.getString() ); // aaa
System.out.println( comp.getString2() ); // aaa
ConcreteDecoratorA.decorate(comp);
System.out.println( comp.getString() ); // [[[ aaa ]]]
System.out.println( comp.getString2() ); // +++ aaa +++
ConcreteDecoratorB.decorate(comp);
System.out.println( comp.getString() ); // *** [[[ aaa ]]] ***
System.out.println( comp.getString2() ); // --- +++ aaa +++ ---
}
}
実装 - その 4
public class StringComponent {
private String str;
public StringComponent(String str) {
this.str = str;
}
public String getString() {
return str;
}
}
public interface StringComponentInterface {
public String getString();
}
public class Client {
public static void main(String[] args) {
StringComponent comp = new StringComponent("xxx");
System.out.println( comp.getString() ); // "xxx"
StringComponentDecoratorAspect.decorate(comp);
System.out.println( comp.getString() ); // "[ xxx ]"
StringComponentDecoratorAspect.decorate(comp);
System.out.println( comp.getString() ); // "[ [ xxx ] ]"
}
}
public aspect StringComponentDecoratorAspect {
declare parents: StringComponent implements StringComponentInterface;
private boolean StringComponentInterface.isDecorated;
private StringComponentInterface StringComponentInterface.decorator;
public static void decorate(StringComponentInterface comp) {
if (comp.decorator == null) {
comp.isDecorated = true;
} else {
comp.decorator.isDecorated = true;
}
}
Object around(final StringComponentInterface comp) :
target(comp) &&
call( String StringComponentInterface.getString() ) &&
if (comp.isDecorated)
{
if (comp.decorator == null) {
StringComponentInterface decorator = new StringComponentInterface() {
public String getString() {
return "[ " + proceed(comp) + " ]";
}
};
comp.decorator = decorator;
}
return comp.decorator.getString();
}
}
更新履歴
todo