2009-11-28 59 views
1

我正在爲一家小公司開發一個簡單的內部ASP.NET應用程序。我設計了數據訪問層,因此它與數據庫無關。這是否匹配任何已知的設計模式?

我有以下:

  • IDataHelper - 要求 方法如FillDataTable(), 的ExecuteNonQuery()等
  • MySqlHelper接口 - 用工具IDataHelper 爲MySQL,目前唯一支持的數據庫我支持 。
  • 靜態數據訪問類 - 封裝數據訪問方法爲 不同部分的應用程序。他們將 的IDataHelper方法調用到 執行查詢。

最後,我有一個靜態類,它爲數據訪問類創建一個IDataHelper來調用。將來它將根據配置文件中指定的數據庫創建適當的幫助程序。現在它只是硬編碼來創建MySqlHelper:

public static class DataHelperContainer 
{ 
    private static IDataHelper dataHelper; 

    public static IDataHelper DataHelper 
    { 
     get { return dataHelper; } 
    } 

    static DataHelperContainer() 
    { 
     string connectionString = ConfigurationManager 
      .ConnectionStrings["myapp"].ConnectionString; 

     // Support for other databases will be added later. 
     dataHelper = new MySqlHelper(connectionString); 
    } 
} 

我的問題是:

  1. 我應該怎麼命名的? 「DataHelperContainer」好像不是 ,因爲這意味着某種 的列表。
  2. 這是一個好還是壞的設計?如果 這很糟糕,它的缺點是什麼?
  3. 這是類似的任何已知的設計 模式?它可以重構爲 是否符合?它似乎很像工廠,但我不確定。

對不起,關於很長的文章和多個問題。 :)

謝謝!

+0

我敢說沒有完全理解這個問題? http://en.wikipedia.org/wiki/Inner-platform_effect – 2010-11-23 22:23:20

回答

4

看起來像Strategy pattern.由於戰略模式將能夠在程序運行期間更改底層功能,並且能夠在不改變數據層基本流程的情況下創建新功能。 [功能通過IHelper接口保證]

+0

我明白了。所以IDataHelper就像一個策略界面,MySQLHelper就像具體的戰略類,DataHelperContainer就像一個上下文類一樣? – 2009-11-28 03:14:52

+0

是的,會的。 – monksy 2009-11-28 03:18:18

+0

不錯!在這種情況下,我會將DataHelperContainer重命名爲DataContext。謝謝您的幫助。 – 2009-11-28 03:20:48

1

對於數據訪問類,它似乎可能是一個數據訪問對象(DAO)模式,但我不確定您是如何實現它的。 Andy West是對的,你肯定有戰略模式。

+0

是的,的確如此。好的觀察。 – 2009-11-28 03:54:50

2
  1. 您可以將其命名爲DataHelperFactory。

  2. 這是一個很好的模式。你絕對不想在全國各地泄漏像ConfigurationManager.ConnectionStrings["myapp"].ConnectionString這樣的東西!一個錯誤是它是靜態的,這使得使用它測試任何代碼變得困難。

  3. 這是最像工廠模式或可能服務定位器(而不是策略)。

目前,您的代碼將是這樣的:

public class MyClass 
{ 
    public void DoSomething() 
    { 
     var helper = DataHelperFactory.Create(); 

     helper.ExecuteNonQuery("some sql"); 
    } 
} 

這並不容易測試,因爲你不得不修改的app.config爲了改變你得到什麼幫助你回來測試。也許你想測試當helper.ExecuteNotQuery拋出異常時會發生什麼。

使用依賴注入,你的類將變爲:

public class MyClass 
{ 
    private IDataHelper helper; 

    public MyClass(IDataHelper helper) 
    { 
     this.helper = helper; 
    } 

    public void DoSomething() 
    { 
     helper.ExecuteNonQuery("some sql"); 
    } 
} 

權衡這裏要說的是,現在你要處理的調用上下文提供的IDataHelper依賴。這就是Unity,Windsor和StructureMap等IoC容器進入的地方。雖然這可能更復雜,但在您的情況下可能不值得。

使用工廠(甚至靜態)是偉大的。它允許您使用其他模式(如裝飾器)來添加其他行爲。考慮要淨化你的SQL字符串,並確保沒有什麼不好被髮送到你的數據庫的情景:

public class SanitizingDataHelper : IDataHelper 
{ 
    private IDataHelper helper; 

    public SanitizingDataHelper(IDataHelper helper) 
    { 
     this.helper = helper; 
    } 

    public void ExecuteNotQuery(string sql) 
    { 
     sql = EscapeHarmfulSql(sql); 
     helper.ExecuteNonQuery(sql); 
    } 

    private string EscapeHarmfulSql(string sql) 
    { 
     ... 
    } 
} 

你的工廠,然後可以做這樣的事情:

public class DataHelperFactory 
{ 
    public IDataHelper Create() 
    { 
     ... 

     var helper = new MySqlDataHelper(connectionString); 

     return new SanitizingDataHelper(helper); 
    } 
} 
+0

工廠是我最初想的(正如你在我的文章中看到的那樣)。我把它變成了靜態的,因爲我只會擁有其中的一個。那麼它如何使它很難測試?我覺得這是一種代碼味道,但我不知道該怎麼做。 – 2009-11-28 04:37:35

+0

感謝您的額外細節。我學到很多東西。 – 2009-11-28 05:59:27

+0

它不是工廠模式。一個工廠模式可以很容易地通過一個字符串來更改僅用於指定數據庫的幫助器。有關工廠模式,請參見:http://www.dofactory.com/Patterns/PatternFactory.aspx。 – monksy 2009-11-28 07:05:53