代码之家  ›  专栏  ›  技术社区  ›  Andy West

这与任何已知的设计模式匹配吗?

  •  1
  • Andy West  · 技术社区  · 14 年前

    我正在为一家小公司开发一个简单的内部ASP.NET应用程序。我设计了数据访问层,所以它是数据库无关的。

    我有以下几点:

    • 辅助助手 -需要 方法,如FillDataTable(), executeNonQuery()等。
    • MySQL助手 -实现IDataHelper 对于mysql,唯一的数据库i 到目前为止的支持。
    • 静态数据访问类 - 封装数据访问方法 应用程序的不同部分。他们 将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. 这和任何已知的设计相似吗 模式?它能重构成 符合一个?看起来很遥远 就像工厂,但我不确定。

    对这篇长文章和多个问题感到抱歉。:)

    谢谢!

    3 回复  |  直到 14 年前
        1
  •  4
  •   monksy    14 年前

    看起来像 Strategy pattern. 使用该策略模式,可以在程序运行时更改基础功能,并且可以在不更改数据层基本流的情况下创建新功能。[通过iHelper接口保证功能]

        2
  •  2
  •   Mike Valenty    14 年前
    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依赖项。这是IOC容器(如Unity、Windsor和StructureMap)进入的地方。但这更复杂,在您的情况下可能不值得这样做。

    使用工厂(甚至静态)是很好的。它允许您使用其他模式(如decorator)来添加其他行为。考虑一个场景,在该场景中,您希望清理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);
        }
    }
    
        3
  •  1
  •   Brian T Hannan    14 年前

    对于数据访问类,它似乎是一个数据访问对象(DAO)模式,但我不确定您是如何实现它的。安迪·韦斯特是对的,你肯定有一个战略模式。