古典的なObserverパターンインターフェイスを定義する2つの抽象クラスSubjectとObserverを作成しました。オブザーバーパターンを実装するためにそれらから派生しています。オブザーバーは次のようになります。
void MyClass::Update(Subject *subject)
{
if(subject == myService_)
{
DoSomething();
}
else if(subject == myOtherService_)
{
DoSomethingElse();
}
}
これは問題なく、誰が何かを変更したかがわかります。ただし、何が変わったのかはわかりません。サブジェクトに最新のデータを照会するだけでよい場合もありますが、サブジェクトで何が変更されたかを正確に知る必要がある場合もあります。Javaでは、おそらく何が変更されたかの詳細を指定するために、notifyObservers()メソッドとnotifyObservers(Object arg)メソッドの両方があることに気づきました。
私の場合、サブジェクトでいくつかの異なるアクションの1つが発生したかどうかを知り、それが特定のアクションである場合は、そのアクションに関連する整数を知る必要があります。
だから私の質問は:
- (Javaのように)汎用的な引数を渡すC ++の方法は何ですか?
- オブザーバーは最高のパターンですか?多分ある種のイベントシステム?
更新
Observerパターンのテンプレート化について説明しているこの記事を見つけました:テンプレートを使用したSubject / Observerパターンの実装。これは、あなたが議論をテンプレート化できるかどうか疑問に思いました。
引数のテンプレート化に関するこのスタックオーバーフローの質問が見つかりました:テンプレートベースのサブジェクトオブザーバーパターン-static_castまたはdynamic_castを使用する必要があります。しかし、OPには誰も答えていない問題があるようです。
もう1つの方法は、Updateメソッドを変更して、次のようにEventArgオブジェクトを取得することです。
void MyClass::Update(Subject *subject, EventArg arg)
{
...
次に、特定の引数データ用にEventArgのサブクラスを作成し、それをupdateメソッド内の特定のサブクラスにキャストし直したと思います。
アップデート2
また、非同期メッセージベースのc ++フレームワークの作成に関する記事も見つかりました。何が変わったかについての詳細を被験者に伝えることを論じるパート2
Boost.Signalsの使用を真剣に検討しています。自分のオブザーバーパターンを使用することは、それが単純な場合には理にかなっていますが、型と引数のテンプレート化は複雑になり始めています。そして、Boost.Signals2のスレッドセーフが必要になる場合があります。
アップデート3
オブザーバーパターンに関する興味深い記事もいくつか見つかりました。
しかし、私はBoost.Signalsを使用するように実装を切り替えました。Boost.Signalsは、目的のために少し肥大化している可能性がありますが、正常に機能しています。そして、おそらく膨らみや速度の懸念は無関係です。