私はオブザーバーパターンの実装戦略を評価しています。要件の1つは、基本Subject
クラスがクラスの派生(具体的な)クラスのメソッドに到達することEvent
です。
プロトタイプの実装では、具体的なイベントクラスで次のコードに到達しました。
// a concrete event
class evZoom : public AbstractEvent
{
public:
virtual void Fill( Subject *aZoomManager)
{
mRatio = dynamic_cast<ZoomManager *>(aZoomManager)->mRatio;
}
int mRatio;
};
今、私は各concreateイベントがこの型キャストを実行しなければならないという事実に悩まされています。
言い換えれば、私はコードの単純さと短さを気にかけています。そこでは、より複雑な基本クラスコード(1つある)と交換して、よりエレガントなコード(多くある)をより具体的なクラスにしたいのです。
したがって、私が思いついた解決策は、メディエーター(つまり、基本クラスと具象クラスの間の1つ)テンプレートを使用して型キャストを行うことです。
完全な実装は次のようになります。
// For Dec
class Subject;
// A non template abstract base class for the Subject class to work with.
class AbstractEvent
{
public:
virtual void Fill ( Subject *aSubject ) = 0;
};
// A mediator class to do the type casting
template < class TSubject >
class Event : public AbstractEvent
{
public:
// This is where we do the type cast.
virtual void Fill ( Subject *aSubject )
{
TSubject *iSubject = dynamic_cast<TSubject *>(aSubject);
// Somehow the compiler knows to call the abstract method below, but if
// we change its name we'll get an infinite loop - cranky.
Fill( iSubject );
}
// And a new abstract method to be implemented by concrete events.
virtual void Fill ( TSubject *aSubject ) = 0;
};
// The subject base class
class Subject
{
public:
// virtual destructor to make this class polymorphic
// so we can cast it dynamically.
virtual ~Subject() { }
void Subscribe( AbstractEvent *aEvent )
{
aEvent->Fill( this );
}
};
// A concrete subject class.
class ZoomManager : public virtual Subject
{
public:
int mRatio;
};
// The concrete event
class evZoom : public Event< ZoomManager >
{
public:
virtual void Fill( ZoomManager *aZoomManager )
{
mRatio = aZoomManager->mRatio;
}
int mRatio;
};
int main(int argc, const char * argv[])
{
ZoomManager iZoomManager;
evZoom *iEvent = new evZoom();
iZoomManager.Subscribe( iEvent );
return 0;
}
これに関する唯一の問題は、より良い解決策があると私が直感していることです。主に、上記のようなメディエータークラスをソースやライブラリで見たことはありませんが、経験が浅い可能性があります。
誰かが上記のもののより良い解決策についてアドバイスできますか?