这是否符合任何已知的设计模式?

时间:2009-11-28 02:40:44

标签: c# asp.net design-patterns naming-conventions

我正在为一家小公司开发一个简单的内部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. 这与任何已知设计类似 图案?可以重构吗? 符合一个?看起来很遥远 像工厂一样,但我不确定。
  4. 对于长篇文章和多个问题感到抱歉。 :)

    谢谢!

3 个答案:

答案 0 :(得分:4)

看起来Strategy pattern.使用策略模式可以在程序运行时更改底层功能,并且能够创建新功能而无需更改数据层的基本流程。 [通过IHelper接口保证功能]

答案 1 :(得分:2)

  1. 您可以将其命名为DataHelperFactory。

  2. 这是一个很好的模式。你肯定不想在整个地方泄漏像ConfigurationManager.ConnectionStrings["myapp"].ConnectionString这样的东西!一个错误是它是静态的,这使得使用它来测试任何代码变得很困难。

  3. 这就像工厂模式或服务定位器(不是策略)。

  4. 目前,您的代码将如下所示:

    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);
        }
    }
    

答案 2 :(得分:1)

对于数据访问类,它似乎可能是数据访问对象(DAO)模式,但我不确定您是如何实现它的。 Andy West是对的,你肯定有一个策略模式。