13

これは技術的な問題ではなく、C++ の設計上の問題です。

ある種の接続、解析ステージ、および抽象ビューを持つプロトコルを管理する必要があるプログラムを設計する必要があるように思われることがよくあります。通常、私は最前線で関心事を分離してプログラムを設計しようとします。

私はオブジェクトの「スタック」で終わり続けます。システムはパーサーの上にあり、パーサーは接続の上にあります(多くの場合、より多くのレイヤーがあります)。次に、これらのオブジェクトはメンバー関数呼び出しを使用してその下のレイヤーを呼び出し (Tx)、コールバック (std::function通常は ) を使用して他の方向 (Rx) からの情報を取得します。

この設計は、複雑さが増し、各レイヤーには次第に大きなコンストラクターなどが必要になるため、実際には劣っているように見えます。また、接続は通常 ASIO のようなものを使用するため、コールバックは一般に異なるスレッド上にあるため、スレッドの安全性について推論するのは困難です。

この構造/機能をよりよく表す設計パターンまたはイディオムはありますか?

編集

簡単な例

class basic_connection {
     basic_connection(std::string address);

     void send(std::string);
     std::function<void(std::string)> on_receive;
};

このようないくつかのクラスがあり、そのレイヤーの状態を保持し、パブリック メンバー関数とコールバックによって結合されています。

この上のレイヤーは、ネットワークのコマンド データ プロセスを受け取り、 を呼び出しますbasic_connection::send。生データを取得しbasic_connection、未処理のレイヤーのコマンドに変換します。

EDIT2:

言及するのを忘れていたもう 1 つの問題は、スタックを介してインターフェイスの一部を転送することになることです。たとえば、トップ レイヤーは接続ステータスを知る必要があります。

4

3 に答える 3

1

一連の要件がなければ、何かを推奨することは困難です。ただし、質問の高レベルの説明から、おそらく他のパターンと組み合わせて、モデル ビュー コントローラー パターンを使用することをお勧めします。設計パターンはあなたの友人であり、使用が適切かどうか、どの程度使用するかを決定するのはあなたです。デザインパターンは非常に悪用されやすく、常に発生しています。

于 2012-11-04T16:49:05.200 に答える
1

あなたがやろうとしているのは、通常「パイプラインの構築」と呼ばれるもののようです。

2 つのレイヤーを接続する簡単な方法の 1 つを次に示します。

class I
{
    virtual void a() = 0;
    virtual void b() = 0;
}

class X
{
    I& m_i;

    X(I& i) : m_i(i) {}

    void onRecv(const char* data, size_t len)
    {
        for (size_t p = 0; p < len; p++)
            switch (data[p])
            {
            case 'a': m_i.a(); break;
            case 'b': m_i.b(); break;
            }
    }
}

class Y : public I
{
    void a() { ... }
    void b() { ... }
}

int main()
{
    X x;
    Y y(x);

    while (...)
        x.onRecv(data,len);
}
于 2012-11-04T18:11:36.783 に答える
0

必要なのは追加の抽象化であるように私には思えます。レイヤーが実際に何であるかを説明する一般的なタイプを設計することから始め、(適切な場合) これらのレイヤーの具体的なプロトコルを考慮せずに、特定のレイヤーごとにそれを改良します。つまり、レイヤー k プロトコルには、レイヤー (k-1) 型のオブジェクトが必要であると言えます。

あなたの説明から、上位レイヤーがすぐ下のレイヤーを構築していて、コンストラクターが膨張していると思います。コンストラクター内の次の下位レイヤーの参照 (おそらくshared_ptrまたはによって実装するのが最適unique_ptrです) を要求し、インターフェイス ユーザーにそのインスタンス化について面倒を見てもらいます。
抽象インターフェースを定義したので、実装方法や使用される特定の下位層プロトコルに煩わされることなく、下位層をポリモーフィックに使用できます。

受信には、通常、同じ方法で実装できるコールバックが必要です。これらを上位層オブジェクトのコンストラクタにインストールし、デストラクタで削除することもできます。


設計時にどのプロトコルが他のどのプロトコルと連携するかがわかっている場合は、プロトコルの実装を次のような下位プロトコルを受け取るテンプレートにすることで、ポリモーフィック呼び出しを置き換えることもできますTcp<Ip<Ethernet<Device>>>

于 2012-11-04T17:03:47.983 に答える