簡體   English   中英

我應該讓這個類靜態嗎?

[英]should I make this class static?

在我工作的項目中,我有查詢/更新數據庫的類,就像這個,

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

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

謝謝,

我不會使該類靜態,而是使用依賴注入並將所需的資源傳遞給該類 這樣您就可以創建一個模擬存儲庫(實現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的博客詳細介紹了一篇很棒的文章,以便開始使用

這取決於。 你需要讓你的程序多線程嗎? 您是否需要連接到多個數據庫? 你是否需要在這堂課中存儲州? 您需要控制連接的生命周期嗎? 您將來需要數據緩存嗎? 如果您對其中任何一個回答“是”,則靜態類會使事情變得尷尬。

我個人的建議是將它作為一個實例,因為這是更多的OO,並將為您提供將來可能需要的靈活性。

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

我強烈建議你遵循DAO模式。 使用像Spring這樣的工具讓你輕松上手。 您所要做的就是配置數據源,您的數據庫訪問和事務將變得輕而易舉。

如果你去靜態課程,你將不得不設計它,使其基本上無國籍。 通常的策略是創建一個具有公共數據訪問功能的基類,然后在特定的類中派生它們,比如加載客戶。

如果對象創建實際上是整個操作的開銷,那么您還可以查看池化預先創建的對象。 但是,我非常懷疑是這種情況。

您可能會發現許多常見的數據訪問代碼都可以構建為靜態方法,但是所有數據訪問的靜態類似乎都在某處丟失了設計。

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

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

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

然后將其分配給全局/公共靜態變量,如果這對於類有意義,即

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM