「優雅」なC++オブザーバーモード実現


C++は強いタイプのプログラミング言語であり、最近は比較的優雅な観察者モードを実現する方法が頭を悩ませている.
イベントに付属するパラメータが異なる場合は、統合されたインタフェースを使用して登録できますか?例えば、私はイベントを定義しました.A、パラメータはintで、イベントBのパラメータはstringです.統一的な登録インタフェースを採用すれば?最初に思いついた方法は,イベントをintで定義しboost::anyでパラメータを伝達し,終了関数をvoid hand(boost::any a)と統一して書く形式であり,問題は,このようなコールバック関数がドキュメントでパラメータ値を制約するしかなく,aが実際にどのようなタイプであるかを知ることが難しいことである.これはvoid handle(int a)ほど直感的ではない.
もう1つのスキームは、各イベントに登録関数を書くことですが、疲れすぎて、イベントが多いとコードが乱れ、イベントの定義がオブジェクトと一緒に書かれ、コードが再利用できず、結合が高すぎます.
最近インスピレーションがキラキラして、次のような自己感覚が優雅です.
/*これは観察者モードの簡略化された実装であり,コードのデカップリングに寄与する.*イベントの定義はOBSERVER_を使用します.EVENTマクロ:*OBSERVER_Event(Name)*Nameはイベントの名前*Paramsはパラメータテーブル*たとえば*OBSERVER_EVENT(MyEvent,int,std::string,long)**必要に応じて、コールバック関数をこのイベント(購読)*observer a;*a.subscribe(Handle);*Nameはイベントの名前です*Handleはコールバック関数で、そのパラメータは、イベントのパラメータテーブルと一致するはずです.*もちろん購読を取り消すこともできます*a.unsubscribe()**イベントが発生した場合、observerオブジェクトからイベント*a.shot()を送信できます.*このオブジェクトは、オブジェクトのデカップリングを支援するためにベースクラスとして使用できます.このような設計の利点は、イベントの定義、コールバックのパラメータテーブル*が厳密に一致しなければならないことです.そうしないと、コードエラーを防止するためにコンパイルエラーが発生します.*特に、パラメータは、コールバック関数が変更できるように参照タイプとして定義できます.イベントを送信するときは、ref()を使用してパラメータをパッケージすることに注意してください. */
もちろん、ライブラリにはマクロとタイプの導出が大量に使われており、コードは読みにくいので、普通の人は見に行かないでください.
しかし、私の原則は、ライブラリのコードがどんなに乱れても大丈夫ですが、インタフェース、使用は必ず簡単です.ファイルが1つしかないライブラリは、かなり簡単に使用できます.
ここではクラスをイベントとして採用し、実装はすべてコンパイラのもので、あなたのコードは正しいかどうか、コンパイルすればいいです.
コールバック関数のパラメータが間違っているなど、誤ったコードを書くのは難しいです.コンパイルは通過できません.
 
完全なテストプログラムを貼り付けます.
#include "observer.hpp"

///     
OBSERVER_EVENT(protocol_data_event, std::string, int )

void handle( const std::string& v, int& x )
{
	std::cout << v << " " << x <<  std::endl;
	x=20;
}

int main(int argc, char* argv[])
{
	using namespace lugce;
	observer a;
	a.subscribe( &handle );
	int i=15;
	a.shot("hello", boost::ref(i) );
	return 0;
}


ライブラリのコードはここで見つけることができます:クリックしてリンクを開きます