AspectJ を使ったデザインパターンの改善と支援 >
Decorator
最終更新日 : 2003/8/28 (2002/9/26 より)
asato <asato@ncfreak.com>
- 注意書き
- テスト環境
- Decorator パターン
- AspectJ を使った Decorator パターンの実装 (2003/3/30 更新)
- テクニックの種類 (2003/4/3 更新)
- 参考文献とリソース (2003/3/29 更新)
- 更新履歴
- todo
注意書き
かなり複雑かつ、実用的でない雰囲気が漂っています。どなたかもっと簡潔に書ける方法に気づいた方は、教えてもらえると嬉しいです。
追記 (2003/3/14): 久しぶりに更新しようと思ってコードを見ていたら、なぜ「オブジェクト Decorator」と「オブジェクトの同一性を意識した Decorator の実装」の二つがあるのかの理由を忘れてしまいました。何か違いがあったはずなんですが・・・
テスト環境
- AspectJ 1.1rc1
- AspectJ 1.1beta4
- AspectJ 1.0.6
Decorator パターン
オブジェクトに責任を動的に追加する。Decorator パターンは、サブクラス化よりも柔軟な拡張方法を提供する。
GoF Decorator パターン
構成要素
- Component クラス:
- ConcreteComponent クラス:
- Decorator クラス:
- ConcreteDecorator クラス:
AspectJ を使った Decorator パターンの実装
実装上の疑問と考慮
Decorator パターンを AspectJ を使ってなんらかの実装を行おうとする場合、いくつかの疑問が現れます:
- なぜ AspectJ を使って Decorator パターンを再実装しようとするのか?
- AspectJ を使って Decorator パターンを実装する場合、オリジナルの Decorator パターンの特徴をどこまで保てば良いのか?
- また、AspectJ を使って実装された Decorator パターンが、どんな特徴を備えているなら、オリジナルの Decorator パターンを AspectJ を使って実装できたと見なせるのか?
- AspectJ を使って実装されたなんらかの結果が、Decorator パターンを実装しているかどうかにこだわる必要があるのか?
なぜ再実装しようとするのか?
回答の1つは、好奇心のためです。AspectJ は Java プログラマにとっての新しい武器の1つかもしれません。AspectJ を使って Decorator パターンの実装しようとする場合、どのような壁にぶち当たるのでしょうか? どうやって実装していけば良いのでしょうか? どの方向に進めていけば良いのでしょうか? AspectJ の文法や使い方は、慣れるまでは大変です。読むのすら大変です。どう書けば良いのかさえ試行錯誤かもしれません。
つまり、(少なくとも著者にとっては) あらかじめどのような結果になるかを予測することは、やや困難なわけです。実際にやってみないと分からない、という状況が少なくありません。従って、最終的にどのような結果になるのか? を知りたい、というのが回答です。
もう1つの回答は、オリジナルの Decorator パターンが少なくとも1つの欠点 (装飾前のオブジェクトと装飾後のオブジェクトは同一でない) を持っているためです。AspectJ を使ってその欠点が克服できるかもしれません。
どこまで特徴を保つのか?
この質問は、AspectJ を使っての Decorator パターンの実装の方向や度合いに影響します。
Decorator パターンを実装できているのか?
Decorator パターンかどうかにこだわる必要があるのか?
テクニックの種類
- 静的 Decorator:
- 一度限りの Decorator:
- オブジェクト Decorator:
- オブジェクトの同一性を意識した Decorator の実装:
確か、下の二つのテクニックは微妙に異なる実装上の目標を持っていたはず (なので別々のテクニックとして紹介している) ですが、具体的にそれが何だったのかは忘れてしまいました。もしかすると、同じものかもしれません。
実装上の目標
下の二つのテクニックともに、基本的な実装上の目標は component オブジェクトを装飾した後でも、オブジェクトの同一性を保つことです。
component オブジェクトを使う側から見た場合、装飾される前の component オブジェクトと装飾後の component オブジェクトが同一でないという結果は、GoF の Decorator パターンでの欠点の 1 つとして考えられています [GoF, p.190]:
Component comp1 = new ConcreteComponent();
Component comp2 = new ConcreteDecorator(comp1);
System.out.println(comp1 == comp2); // false
オブジェクトの同一性を保ちつつ、動的にオブジェクトの振る舞いを変更できる特徴に加え、下の二つのテクニックでは Decorator パターンのもう 1 つの特徴についても満たしています: 複数回の装飾。
Decorator パターンでは ConcreteDecorator クラスは ConcreteComponent クラスと Decorator クラス間の共通のクラスである Component クラスを継承しているため、特定の concrete decorator オブジェクトは component オブジェクトとしても扱えます:
Component comp1 = new ConcreteComponent();
Component comp2 = new ConcreteDecoratorA(comp1);
Component comp3 = new ConcreteDecoratorB(comp2);
静的 Decorator
一度限りの Decorator
オブジェクト Decorator
オブジェクトの同一性を意識した Decorator の実装
実装ノート
- perthis, pertarget でうまく実装できないかどうか検討する。
- どこまでオリジナルの DECORATOR パターンの構造を保つのか。
- 保たなければいけない理由は何か。
- 保たれるのは、何か。なぜ、保たれる結果になるのか。なにが、保たれる結果に影響しているのか。
- どのようにして decorate するのか
- どのようにして componet へのアクセスを得るのか
- どのような状況のクラス群に適用しようとしているのか
- どこまでアスペクトを一般化するのか
- アスペクトは再利用できるのか
- concrete decorator オブジェクトの取り扱い
- concrete decorator オブジェクトも、decorate できるようにするのかどうか
- もし、component オブジェクトが concrete decorator オブジェクト A に decorate されているとして、そのときにその concrete decorator オブジェクト A が concrete decorator オブジェクト B によって decorate されるとすると、どのような影響になるのか。
参考文献とリソース
更新履歴
- 2003.08.28 : 「オブジェクト Decorator」を更新。
- 2003.04.18 : 「オブジェクト Decorator」を更新。
- 2003.04.17 : 「オブジェクト Decorator」を更新。
- 2003.04.16 : 「一度限りの Decorator」を更新。
- 2003.04.15 : 「一度限りの Decorator」を更新。
- 2003.04.11 : 「一度限りの Decorator」を更新。
- 2003.04.09 : 「一度限りの Decorator」を更新。
- 2003.04.08 : 「一度限りの Decorator」を更新。
- 2003.04.07 : 「一度限りの Decorator」を更新。
- 2003.04.06 : 「一度限りの Decorator」を更新。
- 2003.04.05 : 「一度限りの Decorator」を更新。
- 2003.04.04 : 「一度限りの Decorator」を更新。
- 2003.04.03 : 「一度限りの Decorator」を更新。
- 2003.04.02 : 「一度限りの Decorator」を別ページに分割&更新。
- 2003.04.01 : 「オブジェクト Decorator」「オブジェクトの同一性を意識した Decorator の実装」を別ページに分割。/ を追加。
- 2003.03.30 : 「静的 Decorator」を更新。ページを分割。
- 2003.03.28 : 「静的 Decorator」を追加。
- 2003.03.18 : 「AspectJ を使った Decorator パターンの実装」に「実装上の疑問と考慮」を追加!
- 2003.03.16 : 「オブジェクト Decorator」に「実装上の選択肢」を追加!
- 2003.03.14 : 久しぶりに更新。「オブジェクト Decorator」に「実装上の目標」を追加!
- 2002.11.26 :「オブジェクト Decorator」のサンプルコードの実装例 2 を追加! かなりシンプルになってきた。
- 2002.11.24 :「オブジェクト Decorator」を作成! 結構シンプルになってきた!
- 2002.11.23 :「実装方法その2」を更新! 「実装ノート」を作成。
- 2002.11.22 :「decorator の取り外し」の節を追加! 「実装方法その2」を作成!
todo
- ConcreteDecorator deco = ConcreteDecorator.decoratorOf(comp);
- Decorator の導入。
- アスペクトの中にインナー Decorator
- Decorator が状態を持つ場合。
- 各テクニックについて、もっとまともな名前を考える。
- というか、これって本当に Decorator? Strategy の変形じゃないの?
- インナー抽象アスペクトはどこかで使えるか?
- 口調をどっちかに統一する。
- ConcreteDecorator はクラスでなければいけないのか?アスペクトではダメ?
- アスペクトが Decorator の関係を保持すべきか? 他の管理クラスはダメ?
- 前提としている状況を書く。
- GoF の Decorator パターンとの違いを書く。
- getComponent() 経由でなければならないのか? 直接 component ではダメ? 理由は?
- Introduction の順番に注意する。どこで Introduction するかによってコンパイルできるかどうかに違いが現れうる。
- super.methodName でメソッドを呼ぶようにする
- ConcreteDecorator は Component としては扱えない。
- バージョン 1.1beta4 で動作するかどうかすべてのコードをコンパイルチェックする。
[ 戻る ]