1

Qt で GUI フォームを開発していますが、ObserverPattern を実装する方法を知りたいです。フォームは tickerId で識別される多くのデータ ストリームをサブスクライブできます。データ ストリームが到着すると (新しい見積もりが利用可能)、私の PosixClient (ソケット ラッパー) がnotifyObservers()メソッドを起動しupdate()、オブザーバーのメソッドが実行されます。

しかし:

このupdate()メソッドはvoid update()、着信データ レコードを取得してプロットし、何かを数えて、それらを使用する必要があります。どうすればこれを達成できますか、データレコードをオブザーバーに渡す方法は? データは Observable (Observable から派生した MarketData オブジェクト) で利用できます。データが到着したら、それをこの Observable にプッシュし、オブザーバーに通知します。

void PosixClient::tickPrice( TickerId tickerId, TickType field, double price, int canAutoExecute) {
    printf("tradingclient_1: tickPrice: \n");
    for(std::vector<boost::shared_ptr<MarketData> >::iterator it=dataRepository.begin(); 
            it!=dataRepository.end(); it++){
        if((*it)->tickerId==tickerId){
            (*it)->tickPriceData.push_back(tickSizeRecord(field,price,canAutoExecute));
            (*it)->notifyObservers();
            //TODO: start thread to store incoming data in repository
        }
    }
}

次に、それらのvoid update()メソッドが呼び出されます。この関数からデータを取得するために、関数ポインターboost::function<>をコールバックとして渡すことにし、Observer は、observable からの着信データを引数として GUI オブジェクトを指すこの関数ポインターを呼び出します。これは正しいアプローチですか?

struct MarketData : public QuantLib::Observable {
//public:
    MarketData();
    MarketData(IB::Contract c, int tickerId):c(c),tickerId(tickerId){}
    MarketData(const MarketData& orig);
    virtual ~MarketData();
    std::vector<IB::Record> tickPriceData; //market data fed in tickPrice
//private:
    IB::Contract c;
    int tickerId;
};

typedef boost::shared_ptr<MarketData> pMyObservable;
typedef boost::function<void (int tickerId, IB::Record record)> f_action_ptr;

class MarketDataObserver : public QuantLib::Observer{
public:
    MarketDataObserver(pMyObservable obs, f_action_ptr ptr)
        : observable(obs), f_ptr(ptr){
      this->registerWith(observable);
    }
    MarketDataObserver(const MarketDataObserver &observer)
      : Observer(observer),
        observable(observer.observable){ // faction_ptr is not copied!
    }

    void update(){
        data=observable->tickPriceData.back();
        //printf("new data: %l\n",data.price);
        f_ptr(observable->tickerId, data);
    }
private:
    IB::Record data;
    pMyObservable observable;
    f_action_ptr f_ptr;
};

ご注意ください:

私はQtシグナル/スロットメカニズムを認識していますが、私の意見では、データを動的にサブスクライブし、それらをプロットし、Qtフォームに表示し、フォームがキャンセルされたときにサブスクリプションを削除する必要がある場合、Qtシグナル/スロットはここではまったく解決策ではありません. しかし、多分私は間違っています。私ですか?理論的な論争ではなく、実生活からの実際の実用的な例を求めます。

4

1 に答える 1

1

オブザーバー パターンの通常の Qt イディオムは、実際にはシグナルとスロットです。データのソースにシグナルを発行させ、シグナルの引数としてデータを渡します。これが Qt 内で行われる方法です。シグナルは GUI イベントだけに使用されるわけではありません。

于 2013-05-27T16:58:01.507 に答える