2016-06-13 3 views
0

私は最近「通信」オブジェクト/抽象クラスを作成しました。このクラスでは、 「送信」、「受信」、「デバッグ」などの機能を使用できます。C++他のすべてのクラスで(通信)オブジェクトを使用

今、このオブジェクトを基本的に他のすべてのクラスで使用したいので、デバッグメッセージを送信するために使用できます。私がしなければならないだろう瞬間

:私は、このオブジェクトを使用したい他のファイル/クラスのいずれかで

#include "../communication/ICommunication.hpp" 
extern Communication* comm; 

。 これはうまくいくと思われますが、これを行うためのより良い方法があるかどうか疑問に思っていました。

私は名前や実装を覚えていないが、私はこのためのソフトウェアパターンがあると思う。パターンの名前は、私は信じて、人の姓でした。

このパターン(またはこの目的に適したパターン)の名前を知りたいので、実装を自分で試すことができます。 可能であれば、そのパターンが "include and extern"コードよりも優れている理由についてのいくつかの議論もあります。

+1

まず、ヘッダーの内側に「extern」を宣言することができます。この世界を最初に持つことは良い考えかどうかは、ここからは分かりません。 – Thomas

+0

@Thomas d'oh、それは確かに意味があります。そして、それは私の主流の世界にありました(そして、私はそれをグローバルに、あるいは少なくとも "通信"を含めるときには使いたいと思っています)ので、あなたの意見は非常に有効だと思います。 – Paul

答えて

1

このパターンはシングルトンと呼ばれます(しばしば反パターンと呼ばれます)。以下のように見えなければならない:

struct MySingleton { 
static MySingleton& getInstance() { 
    static MySingleton singleton; 
    return singleton; 
} 
}; 

より良いaproachは、コンストラクタにパラメータとして使用するクラスのそれぞれにCommunicationインスタンスを渡すことであろう。 shared_ptrにラップして、すべてのクラスがそれを参照しなくなると、Communicationオブジェクトのデストラクタが自動的に呼び出されるようにすることもできます。

可能であれば、そのパターンが "include and extern"コードよりも優れている理由についてのいくつかの議論もあります。

あなたが遭遇する可能性のある問題は、コミュニケーションオブジェクトのライフタイムがどのように管理されているかということです。最初に使用する前に作成する必要があります。他のクラスや関数がそれを使用した後で破棄する必要があると思います。

シングルトンが通信オブジェクトに適しているかどうかはわかりませんが、サーバーと接続したり、しばらくしてから接続を切断するとします。これはSigletonで行うことができますが、私の経験から、シングルトンは、アプリケーションの全期間のように、寿命が長くなるオブジェクトのためにより多く使用されます。

+0

うん、私は "シングルトン"パターンを探していた。このオブジェクトが(うまくいけば)永遠に生きるであろう埋め込みプロジェクト内で使用されます)。 – Paul

2

このパターン(またはこの目的に適したパターン)の名前を知りたいので、実装を自分で試すことができます。可能であれば、そのパターンが "インクルードとエクスターナル"コードよりも優れている理由についてのいくつかの議論もあります。

現時点で使用するためのベストプラクティスは、インターフェース抽象化と依存性注入されている:あなたはCOMMオブジェクトに使用しようとしている

まず抽象操作:

struct Communicator 
{ 
    virtual void send(const std::string&) = 0; 
    virtual std::string receive() = 0; 
    // etc 
}; 

// injectable Communicator implementation that does nothing; this is useful as 
// a default argument for code that uses communicators: it will show the dependency 
// explicitly, but setting it as a default argument ensures that client code 
// doesn't _have to_ use a communicator, if you don't have one available 
struct NoOpCommunicator: Communicator 
{ 
    void send(const std::string&) override {} 
    std::string receive() override { return {}; } 
} dummy_communicator; // <--- notice this global 

クライアントコード:

class YourClientCode // (uses a Communicator) 
{ 
public: 
    YourClientCode(Communicator& c = dummy_communicator) // communicator instance, 
                 // dependency injected here 
    : com(c) 
    { 
    } 
private: 
    void f() { com.send("f()"); /* ... */ } 

    Communicator& com; 
}; 

auto client1 = YourClientCode{}; 
auto client2 = YourClientCode{ GetActualCommunicatorReference() }; 

これは、comの依存関係をハードコードしないため、+ externよりも優れていますクライアントコードを使用するには、にはにコミュニケータが起動している必要があります。これにより、コードのテスト容易性と再利用性が大幅に向上します。

+0

ええと、これはまた非常に興味深い答えですが、通信オブジェクトに既にある程度の抽象化が組み込まれています。私はシリアル実装(またはUSBやイーサネット、またNoOpなど)でCommunicationsクラスを使うことができます。しかし、私はそれがそれを行うの上品で良い方法であることに同意します。 – Paul

関連する問題