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