2010-07-14 48 views
5

在我在我工作的項目有一個查詢/更新數據庫,這樣一個班,我應該讓這個類是靜態的嗎?

public class CompanyInfoManager 
{ 
    public List<string> GetCompanyNames() 
    { 
     //Query database and return list of company names 
    } 
} 

因爲我不斷創造越來越多類這種,我意識到也許我應該讓這種類型的靜態。通過這樣做,顯而易見的好處是避免了每次需要查詢數據庫時都需要創建類實例。但是因爲對於靜態類,只有一個類的副本,這會導致數百個請求爭用靜態類的一個副本嗎?

感謝,

回答

2

這取決於。你會不會需要讓你的程序多線程?你會不會需要連接到多個數據庫?你會不會需要在這個類中存儲狀態?你需要控制連接的生命週期嗎?你將來需要數據緩存嗎?如果你對這些中的任何一個回答「是」,靜態類會讓事情變得尷尬。

我個人的建議是讓它成爲一個實例,因爲這是更多的面向對象,並會給你以後可能需要的靈活性。

0

如果你去一個靜態類,你就要來設計它,使得它在很大程度上無國籍。通常的策略是創建一個具有通用數據訪問功能的基類,然後在特定的類中派生它們,例如加載客戶。

如果對象創建實際上是整個操作的開銷,那麼您還可以查看將預先創建的對象集中在一起。但是,我非常懷疑這是事實。

您可能會發現很多常見的數據訪問代碼都可以製作成靜態方法,但是對於所有數據訪問而言,靜態類看起來像是設計在某處丟失了。

靜態類對於多線程訪問本身沒有任何問題,但顯然鎖和靜態或共享狀態是有問題的。

1

你必須小心使這個類是靜態的。在Web應用程序中,每個請求都在其自己的線程上處理。如果您不小心,靜態實用程序可能會線程不安全。如果發生這種情況,你不會很高興。

我強烈建議你遵循DAO模式。使用一個像Spring這樣的工具來讓你輕鬆實現。所有你需要做的就是配置一個數據源,你的數據庫訪問和交易將變得輕而易舉。

12

我不會讓該類靜態,而是使用依賴注入並將所需資源傳遞給該類。這樣你可以創建一個模擬庫(實現IRepository接口)來測試。如果您將該類設爲靜態,並且不會傳入您的存儲庫,那麼測試起來非常困難,因爲您無法控制靜態類所連接的內容。

注意:下面的代碼是一個粗略的例子,只是爲了傳達一點,不一定要編譯和執行。

public interface IRepository 
{ 
    public DataSet ExecuteQuery(string aQuery); 
    //Other methods to interact with the DB (such as update or insert) are defined here. 
} 

public class CompanyInfoManager 
{ 
    private IRepository theRepository; 
    public CompanyInfoManager(IRepository aRepository) 
    { 
     //A repository is required so that we always know what 
     //we are talking to. 
     theRepository = aRepository; 
    } 

    public List<string> GetCompanyNames() 
    { 
     //Query database and return list of company names 
     string query = "SELECT * FROM COMPANIES"; 
     DataSet results = theRepository.ExecuteQuery(query); 
     //Process the results... 
     return listOfNames; 
    } 
} 

測試CompanyInfoManager:

//Class to test CompanyInfoManager 
public class MockRepository : IRepository 
{ 
    //This method will always return a known value. 
    public DataSet ExecuteQuery(string aQuery) 
    { 
     DataSet returnResults = new DataSet(); 
     //Fill the data set with known values... 
     return returnResults; 
    } 
} 

//This will always contain known values that you can test. 
IList<string> names = new CompanyInfoManager(new MockRepository()).GetCompanyNames(); 

我不想羅嗦了大約依賴注入。 Misko Hevery's blog詳細瞭解great post to get started

+0

謝謝大腦。我有類似於你的例子的東西。我給出的示例代碼是我的課程的一個超級精簡版本。是的,我也喜歡Repository模式。另外,我使用CastleWindsor作爲我的DI容器。 – sean717 2010-07-14 22:53:04

0

通過使該類爲靜態,您將有一個難以測試的時間單元,因爲您可能必須以非清晰的方式在內部管理連接字符串的讀取,或者通過在類中讀取它從配置文件或從管理這些常量的某個類請求它。我寧願實例這樣的類以傳統方式

var manager = new CompanyInfoManager(string connectionString /*...and possible other dependencies too*/) 

,然後將其分配給全球/公共靜態變量,如果是有道理的爲類,即

//this can be accessed globally 
public static CompanyInfoManager = manager; 

所以現在你不會爲你的單元測試犧牲任何靈活性,因爲所有類的依賴都是通過構造函數傳遞給它的。

相關問題