ContextをInterfaceにする訳
http://d.hatena.ne.jp/fkm/20061125/p1
インターフェースにするとDoOkeyAction()の実装の部分で、インターフェースを実装してるクラスのフィールドとかメソッドとかを使って何かしたあとstate_->DoOkeyAction(this);とできる。
が正解。StateがState保持者であるContextに対して影響を与える必要がある場合、Contextのinterfaceを知っていないといけない。
SetState以外にもたとえば、
interface HogeContext {
void 逃げる();
void 攻撃();
void SetState(HogeState s);
}
interface HogeState {
void 攻撃された(HogeContext *c);
}
class 強気State : HogeState {
void 攻撃された(HogeContext *c) {
if (HPヤバイ) {
s = new 弱気State();
c->SetState(s);
s->攻撃された(c);
} else {
c->攻撃();
}
}
}
class 弱気State : HogeState {
void 攻撃された(HogeContext *c) {
c->逃げる();
}
}となる。
だから、
thisで実装しているクラス(のインスタンス)のポインタが渡せるということは、危険な香りがするがdynamic_castで元に戻せる?
をしてはダメ。dynamic_castするんじゃなくて、Stateからアクセスできる関数はinterfaceで宣言しないと、Contextがinterfaceになっている理由がなくなっちゃう。
ちなみに、State保持者であるContextは一つだけである事が多いので、Stateクラスはコンストラクタで保持者であるContextへの参照をもらえば、毎回引数としてContextを受け取る必要はない。