2011-07-14 64 views
2

作爲一個框架設計的結果,我使用一個插件作爲目標,我已經將一部分代碼實現爲一個單例。這個類負責處理與我在框架內進行通信的外部程序的連接。函數返回引用,失敗時返回什麼?

但是,啓用外部通信是一種運行時設置,如果它被禁用,我不想允許從框架內的模型訪問它。我一直在使用,這是經常在這裏推薦的版本中實現它:,因爲ServiceEnabledfalse

class Communicator { 
public: 
    static Communicator& getInstance() { 
     static Communicator instance; 
     return instance; 
    } 
    // ... 
private: 
    static bool ServiceEnabled; 
    // Constructors, operator=, etc ... 
} 

現在,我不希望讓getInstance返回一個有效的Communicator。但是,因爲我返回一個參考,我不能簡單地返回0或某些這樣的...什麼適當的行爲是什麼?請注意,即使ServiceEnabled爲假,繼續執行也是完全有效的,所以如果是的話我不能中止。

+4

豈不更好地在這裏返回一個指針滿足您的需求? (我假設拋出一個異常不是你以後的事情。) – Mat

+1

什麼對象是錯誤的'ServiceEnabled'成員? – aschepler

+0

@aschepler:哎呦。固定。 – carlpett

回答

4

添加公共功能

static bool IsServiceEnabled(); 

,並拋出一個異常在getInstance,當它被稱爲同時ServiceEnabled ==假;

0

我會再次考慮設計決定,然後可能會創建一個異常類並拋出它。這當然需要在另一端處理可能的例外。

1

正確的行爲是當你遇到一個失敗拋出異常:

#include <stdexcept> 

class Communicator { 
public: 
    static Communicator& getInstance() { 
     static Communicator instance; 
     if (ServiceEnabled) 
      return instance; 
     else 
      throw std::exception("Get communicator while service is not enabled"); 
    } 
    // ... 
private: 
    static bool ServiceEnabled; 
    // Constructors, operator=, etc ... 
} 
0

也許你應該考慮用假ServiceEnabled爲「有效」

要實現溝通,你需要一種方法bool IsEnabled()和您的其他方法都需要檢查servoce啓用,最經常,如果立即返回不是這樣。

0

爲什麼不讓類別忽略所有帶副作用的調用?這樣你可以調用你想要的所有功能,而不必擔心它是否打開或關閉。提供一個「IsServiceEnabled」(如Henrik答案)以允許用戶知道它是否應該進行通信。

4

實際上有很多可能性......這是一個列表的開始,沒有特定的順序。

指針

class Communicator { 
public: 
    static Communicator const* Instance(); // returns 0 if not Enabled 
}; 

這實際上可以通過一個「安全」的指針類型替換(即斷言/拋出,如果指針爲空,有人試圖使用它)。

查詢+扔

class Communicator { 
public: 
    static bool IsEnabled(); 
    static Communicator const& Instance(); // throw if not Enabled 
}; 

空對象

class Communicator { 
public: 
    static Communicator const& Instance(); //returns a null instance if not Enabled 

    void doit() { if (!enabled) { return; } } 
}; 

我個人不喜歡最後一個了,因爲隱藏了一個事實,即它是沒有啓用,可防止用戶儘早注意到問題。想想一個交易系統,它確信在將所有事情都發送到/dev/null時已經註冊了它的交易...

0

如果您確實希望能夠在運行時切換通信,您可能需要擔心用戶可以在啓用時保存Communicator參考,並稍後嘗試在禁用時使用它。 當然,這個問題對於單身人士來說並不是唯一的。
你可以間接引入另一層處理:

class CommunicatorImpl 
{ 
public: 
    virtual bool isEnabled() const = 0; 
    virtual void doSomething() = 0; 
}; 

class CommunicatorImpl_Enabled : public CommunicatorImpl 
{ 
    public: 
     virtual bool isEnabled() const { return true; } 
     virtual void doSomething() { /* Do something... */} 
}; 


class CommunicatorImpl_Disabled : public CommunicatorImpl 
{ 
    public: 
     virtual bool isEnabled() const { return false; } 
     virtual void doSomething() { throw CommunicationIsDisabled("SRY"); } 
}; 



class Communicator { 
public: 
    static Communicator& getInstance() { 
     static Communicator instance; 
     return instance; 
    } 

    void enable() { m_impl = &m_enabled; } 
    void disable() { m_impl = &m_disabled; } 
    bool isEnabled() const { return m_impl->isEnabled(); } 
    void doSomething() { m_impl->doSomething(); } 

private: 
    CommunicatorImpl* m_impl; 
    CommunicatorImpl_Enabled m_enabled; 
    CommunicatorImpl_Disabled m_disabled; 
} 
相關問題