打造属于你的提供者(Provider = Strategy + Factory Method)

 

1.1.1 摘要

在日常系统设计中,我们也许听说过提供者模式,甚至几乎每天都在使用它,在.NET Framkework 2.0中微软提出了提供者模式(Provider),所以我们可以发现.NET Framkework中有很多类命名都含有“Provider”,例如:IFormatProvider,RSACryptoServiceProvider等等,由此可见它们都间接或直接使用了提供者模式这一设计思想,现在让我们来介绍一下提供者模式(Provider)。

1.1.2 正文

首先让我们通过提供者模式(Provider)结构图,了解什么是提供者模式(Provider)。

图1提供者模式(Provider)结构图

通过上面的结构图我们发现提供者模式(Provider),并没有想象中的那么复杂而且整个结构就是使用了一些继承关系而已。

提供者模式(Provider)的结构图,和我们熟悉的策略模式(Strategy)结构基本一致就是通过继承扩展不同种类的算法。

策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。

图2策略模式(Strategy)结构图

所以很多人都喜欢把提供者模式(Provider)和策略模式(Strategy)进行对比,更甚至有些人认为就是策略模式(Strategy),其实不然我们可以发现每种提供者它们都是继承于一个基类ProviderBase,无论是系统还是自定义的提供者都必须继承于它。

现在让我们看看抽象类ProviderBase。

public abstract class ProviderBase
{
    // Fields
    private string _Description;
    private bool _Initialized;
    private string _name;

    // Methods
    protected ProviderBase();
    public virtual void Initialize(string name, NameValueCollection config);

    // Properties
    public virtual string Description { get; }
    public virtual string Name { get; }
}

通过上面的代码我们发现,ProviderBase只包含一些描述字段和属性,还有就是一个无参构造函数和一个初始化方法Initialize(string name, NameValueCollection config)。该方法是提供者模式实现动态调用的核心方法(DI的实现)。

在ProviderBase中提供了Initialize方法实现和统一签名,然后让提供者重写该方法,现在我们又有问题了究竟这个方法要实现什么功能呢?让我们看看Initialize方法的实现吧!

public virtual void Initialize(string name, NameValueCollection config)
{
    lock (this)
    {
        if (this._Initialized)
        {
            throw new InvalidOperationException(
                SR.GetString("Provider_Already_Initialized"));
        }
        this._Initialized = true;
    }
    if (name == null)
    {
        throw new ArgumentNullException("name");
    }
    if (name.Length == 0)
    {
        throw new ArgumentException(
            SR.GetString("Config_provider_name_null_or_empty"), "name");
    }
    this._name = name;
    if (config != null)
    {
        this._Description = config["description"];
        config.Remove("description");
    }
}

其实这个方法功能很简单就是去读我们配置文件相应节点的值, 现在我们知道可以通过重新 Initialize 方法,可以实现从配置文件中读取 Provider 的信息(如:name,type,connectionString 等)。我们都知道继承使得类之间的耦合度增加, 这就是策略模式的一个缺点具体算法通过继承来进行扩展。但我们看到提供者模式(Provider)使用了一种比较灵活方法对具体提供者进行扩展。

图 3 ASP.NET中的提供者模式(Provider)

通过上图我们发现.NET中的MembershipProvider,RoleProvider,SiteMapProvider等提供者都必须继承于ProviderBase类,接着是具体实现提供者的类。除此之外,我们自定义提供者都必须继承于ProviderBase类。

我们对于提供者模式(Provider)有了初步的认识,那么现在让我们定义属于自己的提供者吧!

假设我们要设计数据库提供者,考虑到我们系统的灵活性和扩展性,我们应该使系统可以在不同数据之间无缝切换,由于数据库的种类有:SqlServer,Oracle,MySql,SQLite等,首先定义一个抽象类DataProvider让具体数据提供者来实现它。

图 4 DataProvider的设计

我们定义一个DataProvider类继承于ProviderBase,然后添加数据连接字符串,存储过程名字和参数属性,最后就是一系列的对数据库操作方法。

/// <summary>
/// Defines the methods that Data providers should be implemented.
/// </summary>
public abstract class DataProvider : ProviderBase
{

    /// <summary>
    /// Runs the specified transaction.
    /// </summary>
    /// <param name="transaction">The transaction.</param>
    public abstract void Run(DbTransaction transaction);

    /// <summary>
    /// Runs the specified transaction.
    /// </summary>
    /// <param name="transaction">The transaction.</param>
    /// <param name="parameters">The stored procedure  parameters.</param>
    public abstract void Run(DbTransaction transaction, DbParameter[] parameters);

    //public abstract DbDataReader Run(DbParameter[] parameters);

    /// <summary>
    /// Runs the specified connection string.
    /// </summary>
    /// <param name="connectionString">The connection string.</param>
    /// <param name="parameters">The stored procedure  parameters.</param>
    /// <returns>Returns dataset.</returns>
    public abstract DataSet Run(string connectionString, DbParameter[] parameters);

    /// <summary>
    /// Runs the scalar.
    /// </summary>
    /// <param name="connectionString">The connection string.</param>
    /// <param name="parameters">The stored procedure  parameters.</param>
    /// <returns>Returns an object.</returns>
    public abstract object RunScalar(string connectionString, DbParameter[] parameters);

    /// <summary>
    /// Runs the scalar.
    /// </summary>
    /// <param name="transaction">The transaction.</param>
    /// <param name="parameters">The stored procedure  parameters.</param>
    /// <returns></returns>
    public abstract object RunScalar(SqlTransaction transaction, DbParameter[] parameters);

    /// <summary>
    /// Runs the specified connectionstring.
    /// </summary>
    /// <param name="connectionstring">The connectionstring.</param>
    /// <returns></returns>
    public abstract DataSet Run(string connectionstring);

    /// <summary>
    /// Runs this instance.
    /// </summary>
    public abstract void Run();

    /// <summary>
    /// Runs the specified parameters.
    /// </summary>
    /// <param name="parameters">The stored procedure  parameters.</param>
    /// <returns></returns>
    public abstract DataSet Run(DbParameter[] parameters);

    /// <summary>
    /// Runs the specified command type.
    /// </summary>
    /// <param name="commandType">Type of the command.</param>
    /// <param name="commandText">The command text stored procedure or sql queries.</param>
    /// <returns></returns>
    public abstract DbDataReader Run(CommandType commandType, string commandText);

    /// <summary>
    /// Gets or sets the stored procedure parameters.
    /// </summary>
    /// <value>
    /// The stored procedure parameters.
    /// </value>
    public DbParameter[] Parameters { get; set; }

    /// <summary>
    /// Gets or sets the name of the stored procedure.
    /// </summary>
    /// <value>
    /// The name of the stored procedure.
    /// </value>
    public string StoredProcedureName { get; set; }

    /// <summary>
    /// Gets the default connection string from webconfig file.
    /// </summary>
    protected string ConnectionString
    {
        get { return ConfigurationManager.ConnectionStrings["SQLCONN"].ToString(); }
    }
}

上面我们完成了抽象的提供者,这里仅仅是一些抽象的方法并没有具体的实现,所以我们要通过具体的提供者来实现这些抽象的方法。接下来让我们定义具体的提供者SqlDataProvider和OracleDataProvider。

图 5具体提供者设计

/// <summary>
/// The implementor of DataProvder.
/// </summary>
public class SqlDataProvider : DataProvider
{

    #region Fields

    private string _connection = string.Empty;

    #endregion

    /// <summary>
    /// Default parameterless constructor used by Reflection.
    /// </summary>
    public SqlDataProvider()
    {
        // Just used by Reflection.
    }

    /// <summary>
    /// Initializes the provider.
    /// </summary>
    /// <param name="name">The name of provider, setting in webconfig file.</param>
    /// <param name="config">The value collection of config.</param>
    public override void Initialize(string name, NameValueCollection config)
    {
        // Due to ProviderBase has check name and config are available or not,
        // So no need validate name and config.
        base.Initialize(name, config);
        _connection = config["connectionString"];

        if (string.IsNullOrEmpty(_connection))
            throw new ConfigurationErrorsException("Connection string can't empty.");
    }

    /// <summary>
    /// Runs the specified transaction.
    /// </summary>
    /// <param name="transaction">The transaction.</param>
    public override void Run(DbTransaction transaction)
    {
        SqlHelper.ExecuteNonQuery(transaction as SqlTransaction,
            CommandType.StoredProcedure, StoredProcedureName, Parameters);
    }

    /// <summary>
    /// Runs the specified transaction.
    /// </summary>
    /// <param name="transaction">The transaction.</param>
    /// <param name="parameters">The parameters.</param>
    public override void Run(DbTransaction transaction, DbParameter[] parameters)
    {
        SqlHelper.ExecuteNonQuery(transaction as SqlTransaction,
            CommandType.StoredProcedure, StoredProcedureName, parameters as SqlParameter[]);
    }

    /// <summary>
    /// Runs the specified connection string.
    /// </summary>
    /// <param name="connectionString">The connection string.</param>
    /// <param name="parameters">The parameters.</param>
    /// <returns></returns>
    public override DataSet Run(string connectionString, DbParameter[] parameters)
    {
        DataSet ds = SqlHelper.ExecuteDataset(connectionString, StoredProcedureName, parameters);
        return ds;
    }

    /// <summary>
    /// Runs the specified parameters.
    /// </summary>
    /// <param name="parameters">The stored procedure  parameters.</param>
    /// <returns></returns>
    public override DataSet Run(DbParameter[] parameters)
    {
        DataSet ds = SqlHelper.ExecuteDataset(ConnectionString, StoredProcedureName, parameters);

        return ds;

    }

    /// <summary>
    /// Runs the scalar.
    /// </summary>
    /// <param name="connectionString">The connection string.</param>
    /// <param name="parameters">The parameters.</param>
    /// <returns></returns>
    public override object RunScalar(string connectionString, DbParameter[] parameters)
    {
        object obj = SqlHelper.ExecuteScalar(connectionString, StoredProcedureName, parameters);

        return obj;
    }

    /// <summary>
    /// Runs the scalar.
    /// </summary>
    /// <param name="transaction">The transaction.</param>
    /// <param name="parameters">The parameters.</param>
    /// <returns></returns>
    public override object RunScalar(SqlTransaction transaction, DbParameter[] parameters)
    {
        object obj = SqlHelper.ExecuteScalar(transaction, StoredProcedureName, parameters);

        return obj;
    }

    /// <summary>
    /// Runs the specified connectionstring.
    /// </summary>
    /// <param name="connectionstring">The connectionstring.</param>
    /// <returns></returns>
    public override DataSet Run(string connectionstring)
    {
        DataSet ds = SqlHelper.ExecuteDataset(connectionstring,
            CommandType.StoredProcedure, StoredProcedureName);

        return ds;

    }

    /// <summary>
    /// Runs this instance.
    /// </summary>
    public override void Run()
    {
        SqlHelper.ExecuteNonQuery(ConnectionString,
            CommandType.StoredProcedure, StoredProcedureName, Parameters);
    }

    /// <summary>
    /// Runs the specified parameters.
    /// </summary>
    /// <param name="commandType">Type of the command.</param>
    /// <param name="commandText">The command text stored procedure or sql queries.</param>
    /// <returns></returns>
    public override DbDataReader Run(CommandType commandType, string commandText)
    {
        SqlDataReader dr = SqlHelper.ExecuteReader(ConnectionString, CommandType.Text, commandText);

        return dr;

    }

    public SqlParameter[] Parameters { get; set; }

}

我们很快就完成了SqlDataProvider类,这是由于我们把具体的实现都放在了SqlHelper中。在SqlHelper中包含具体的数据库操作方法,在其中包含了一些烦琐的数据库操作方法,如果我们说要让大家自己去完成这个Helper类,那么肯定是一个很痛苦的过程,而且严重影响了开发的效率,考虑到数据库操作方法的可重用性微软已经给我们提供了对SqlServer操作的Helper类(包含C#和VB)。

现在SqlDataProvider类基本完成了,接着我们创建一个DataProviderManager类,在它里面提供工厂方法用来创建提供者对象。

图 6 DataProviderManager设计

在DataProviderManager类中的CreateProvider方法负责创建提供者对象(如:SqlDataProvider和OracleDataProvider)。

/// <summary>
/// The factory method to creates the provider instance.
/// </summary>
/// <returns>The instances of provider.</returns>
public static object CreateProvider()
{
    LoadProviders();

    return _provider;
}

/// <summary>
/// Loads the providers by webconfig setting.
/// </summary>
private static void LoadProviders()
{
    // providers are loaded just once
    if (null == _providers)
    {
        // Synchronize the process of loading the providers
        lock (SyncLock)
        {
            // Double confirm that the _provider is still null.
            if (null == _provider)
            {
                try
                {
                    // Reads the webconfig file corresponding node.
                    DataProviderSection section = (DataProviderSection)
                                                  WebConfigurationManager.GetSection(
                                                  "system.web/dataProviderService");

                    _providers = new DataProviderCollection();

                    // Creates provider instance, and invokes ProviderBase's Initialize function.
                    ProvidersHelper.InstantiateProviders(section.Providers, Providers, typeof(DataProvider));

                    // Gets the default in the collection.
                    _provider = Providers[section.DefaultProvider];
                }
                catch
                {
                    throw new ProviderException("Can't create instance");
                }
            }
        }
    }
}

通过上面的代码我们hard code获取提供者信息的配置文件节点,那么DataProviderManager类根据配置文件设置来实例化提供者对象,接下来让我们设置配置文件。

图 7 提供者模式配置文件设置

首先我们在configSections中,设置自定义数据库提供者名称(dataProviderService)和命名空间,接着我们在web节点中配置dataProviderService,在其中我们配置了默认的数据库提供者为SqlDataProvider,接着我们再设置其它数据库提供者OracleDataProvider。

现在我们已经完成了自定义数据库提供者了,那么接下来让我们通过一个简单的web界面程序来测试一下吧!

图 8 界面效果图

由于时间的关系我们已经把界面设计好了,现在让我们测试一下数据库提供者。

图 9 测试效果图

/// <summary>
/// Insert data into to database.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnAdd_Click(object sender, EventArgs e)
{
    try
    {
        if (!String.IsNullOrEmpty(this.txtUserName.Text.Trim()))
        {
            UserInfoParameters userInfo = new UserInfoParameters(this.txtUserName.Text.Trim());
            DataProvider provider = DataProviderManager.CreateProvider() as DataProvider;
            provider.StoredProcedureName = "sp_AddUsertt";
            provider.Run(userInfo.Parameters);
            this.lblMsg.Text = "Save successful.";
        }

    }
    catch (Exception ex)
    {
        this.lblMsg.Text = "Save failed.";
        throw ex;
    }
}

上面我们调用SqlDataProvider把用户名写入到数据库。

    /// <summary>
    /// Get id from database.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnSelect_Click(object sender, EventArgs e)
    {
        try
        {
            if (!String.IsNullOrEmpty(this.txtUserName.Text.Trim()))
            {

                UserInfoParameters userInfo = new UserInfoParameters(this.txtUserName.Text);

                DataProvider provider = DataProviderManager.CreateProvider() as DataProvider;

                string strSql = String.Format(
                    "SELECT UserID FROM UserInfo WHERE UserName = '{0}'", this.txtUserName.Text);
                SqlDataReader dr = provider.Run(CommandType.Text, strSql) as SqlDataReader;
                while (dr.Read())
                {
                    this.lblMsg.Text = "The user id is: " + dr[0].ToString();
                }
            }

        }

        catch (Exception ex)
        {
            this.lblMsg.Text = "This id not existed";
            throw ex;
        }
    }
}

接着我们根据用户名从数据库中读取用户id。

/// <summary>
/// Sets stored procedure parameters.
/// </summary>
public class UserInfoParameters
{

    private string _userName;

    public UserInfoParameters(string userName)
    {
        _userName = userName;
        Build();
    }

    private void Build()
    {
        SqlParameter[] sqlParameters = { new SqlParameter("@UserName", _userName) };
        Parameters = sqlParameters;
    }

    public SqlParameter[] Parameters { get; set; }
}

我们通过SqlDataProvider提供者成功把User Name写入数据库中,而且在数据库中生成的id为11。

1.1.3 总结

通过本文的介绍相信大家对提供者模式(Provider)有了初步的了解,在我看来提供者模式不仅仅是包含策略模式(Strategy)思想,而且它通过工厂方法(Factory Method)更好地改善了继承使得耦合度增加的缺点,所以说提供者包含了策略模式(Strategy)和工厂方法(Factory Method)设计思想。

我们知道所有提供者模式(Provider)必须继承于抽象基类ProviderBase,然后我们就可以定义各种各样的提供者。

希望通过阅读本文后大家对于提供者模式有更深的了解。

提供者模式参考资料

Provider Model Design Pattern and Specification, Part 1

The ASP.NET 2.0 Provider Model.

Designing loosely coupled components in .NET  Provider Pattern

Demo下载

 
 
 
 

设计模式 - Provider Pattern(提供者模式)

2010年11月16日 09:36:00 ztmaster 阅读数:4620
 

介绍
为一个API进行定义和实现的分离。

示例
有一个Message实体类,对它的操作有Insert()和Get()方法,持久化数据在SqlServer数据库中或Xml文件里。根据配置文件中的配置来决定数据持久化方案是使用SqlServer数据库还是Xml文件。

MessageModel

using System;

namespace Pattern.Provider
{
    /// <summary>
    /// Message实体类
    /// </summary>
    public class MessageModel
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="msg">Message内容</param>
        /// <param name="pt">Message发布时间</param>
        public MessageModel(string msg, DateTime pt)
        {
            this._message = msg;
            this._publishTime = pt;
        }

        private string _message;
        /// <summary>
        /// Message内容
        /// </summary>
        public string Message
        {
            get { return _message; }
            set { _message = value; }
        }

        private DateTime _publishTime;
        /// <summary>
        /// Message发布时间
        /// </summary>
        public DateTime PublishTime
        {
            get { return _publishTime; }
            set { _publishTime = value; }
        }
    }
}

MessageProvider

using System.Configuration.Provider;
using System.Collections.Generic;

namespace Pattern.Provider
{
    /// <summary>
    /// 操作Message抽象类
    /// </summary>
    public abstract class MessageProvider : ProviderBase
    {
        /// <summary>
        /// 插入Message
        /// </summary>
        /// <param name="mm">Message实体对象</param>
        /// <returns></returns>
        public abstract bool Insert(MessageModel mm);

        /// <summary>
        /// 获得Message
        /// </summary>
        /// <returns></returns>
        public abstract List<MessageModel> Get();
    }
}

SqlMessageProvider

using System;
using System.Collections.Specialized;
using System.Collections.Generic;

using System.Configuration.Provider;
using System.Configuration;

namespace Pattern.Provider
{
    /// <summary>
    /// Sql方式操作Message
    /// </summary>
    public class SqlMessageProvider : MessageProvider
    {
        private string _connectionString;

        /// <summary>
        /// 插入Message
        /// </summary>
        /// <param name="mm">Message实体对象</param>
        /// <returns></returns>
        public override bool Insert(MessageModel mm)
        {
            // 代码略
            return true;
        }

        /// <summary>
        /// 获取Message
        /// </summary>
        /// <returns></returns>
        public override List<MessageModel> Get()
        {
            List<MessageModel> l = new List<MessageModel>();
            l.Add(new MessageModel("SQL方式,连接字符串是" + this._connectionString, DateTime.Now));

            return l;
        }

        /// <summary>
        /// 初始化提供程序。
        /// </summary>
        /// <param name="name">该提供程序的友好名称。</param>
        /// <param name="config">名称/值对的集合,表示在配置中为该提供程序指定的、提供程序特定的属性。</param>
        public override void Initialize(string name, NameValueCollection config)
        {
            if (string.IsNullOrEmpty(name))
                name = "MessageProvider";

            if (null == config)
                throw new ArgumentException("config参数不能为null");

            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "SqlServer操作Message");
            }

            base.Initialize(name, config);

            string temp = config["connectionStringName"];
            if (temp == null || temp.Length < 1)
                throw new ProviderException("connectionStringName属性缺少或为空");

            _connectionString = ConfigurationManager.ConnectionStrings[temp].ConnectionString;
            if (_connectionString == null || _connectionString.Length < 1)
            {
                throw new ProviderException("没找到'" + temp + "'所指的连接字符串,或所指连接字符串为空");
            }

            config.Remove("connectionStringName");
        }
    }
}

XmlMessageProvider

using System;
using System.Collections.Specialized;
using System.Collections.Generic;

using System.Configuration.Provider;
using System.Configuration;

namespace Pattern.Provider
{
    /// <summary>
    /// Xmll方式操作Message
    /// </summary>
    public class XmlMessageProvider : MessageProvider
    {
        private string _connectionString;

        /// <summary>
        /// 插入Message
        /// </summary>
        /// <param name="mm">Message实体对象</param>
        /// <returns></returns>
        public override bool Insert(MessageModel mm)
        {
            // 代码略
            return true;
        }

        /// <summary>
        /// 获取Message
        /// </summary>
        /// <returns></returns>
        public override List<MessageModel> Get()
        {
            List<MessageModel> l = new List<MessageModel>();
            l.Add(new MessageModel("XML方式,连接字符串是" + this._connectionString, DateTime.Now));

            return l;
        }

        /// <summary>
        /// 初始化提供程序。
        /// </summary>
        /// <param name="name">该提供程序的友好名称。</param>
        /// <param name="config">名称/值对的集合,表示在配置中为该提供程序指定的、提供程序特定的属性。</param>
        public override void Initialize(string name, NameValueCollection config)
        {
            if (string.IsNullOrEmpty(name))
                name = "MessageProvider";

            if (null == config)
                throw new ArgumentException("config参数不能为null");

            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "XML操作Message");
            }

            base.Initialize(name, config);

            string temp = config["connectionStringName"];
            if (temp == null || temp.Length < 1)
                throw new ProviderException("connectionStringName属性缺少或为空");

            _connectionString = ConfigurationManager.ConnectionStrings[temp].ConnectionString;
            if (_connectionString == null || _connectionString.Length < 1)
            {
                throw new ProviderException("没找到'" + temp + "'所指的连接字符串,或所指连接字符串为空");
            }

            config.Remove("connectionStringName");
        }
    }
}

MessageProviderCollection

using System.Configuration.Provider;
using System;

namespace Pattern.Provider
{
    /// <summary>
    /// Message的Provider集合类
    /// </summary>
    public class MessageProviderCollection : ProviderCollection
    {
        /// <summary>
        /// 向集合中添加提供程序。
        /// </summary>
        /// <param name="provider">要添加的提供程序。</param>
        public override void Add(ProviderBase provider)
        {
            if (provider == null)
                throw new ArgumentNullException("provider参数不能为null");

            if (!(provider is MessageProvider))
                throw new ArgumentException("provider参数类型必须是MessageProvider.");

            base.Add(provider);
        }
    }
}

MessageProviderConfigurationSection

using System.Configuration;

namespace Pattern.Provider
{
    /// <summary>
    /// Message的Provider的配置
    /// </summary>
    public class MessageProviderConfigurationSection : ConfigurationSection
    {
        private readonly ConfigurationProperty _defaultProvider;
        private readonly ConfigurationProperty _providers;
        private ConfigurationPropertyCollection _properties;
        
        /// <summary>
        /// 构造函数
        /// </summary>
        public MessageProviderConfigurationSection()
        {
            _defaultProvider = new ConfigurationProperty("defaultProvider", typeof(string), null);
            _providers = new ConfigurationProperty("providers", typeof(ProviderSettingsCollection), null);
            _properties = new ConfigurationPropertyCollection();

            _properties.Add(_providers);
            _properties.Add(_defaultProvider);
        }

        /// <summary>
        /// Message的默认的Provider
        /// </summary>
        [ConfigurationProperty("defaultProvider")]
        public string DefaultProvider
        {
            get { return (string)base[_defaultProvider]; }
            set { base[_defaultProvider] = value; }
        }

        /// <summary>
        /// Message的所有的Provider集合
        /// </summary>
        [ConfigurationProperty("providers", DefaultValue = "SqlMessageProvider")]
        [StringValidator(MinLength = 1)]
        public ProviderSettingsCollection Providers
        {
            get { return (ProviderSettingsCollection)base[_providers]; }
        }

        /// <summary>
        /// Message的Provider的属性集合
        /// </summary>
        protected override ConfigurationPropertyCollection Properties
        {
            get { return _properties; }
        }
    }
}

Message

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Web.Configuration;

namespace Pattern.Provider
{
    /// <summary>
    /// 暴露给客户端用的Message的类(Context)
    /// </summary>
    public class Message
    {
        private static bool m_isInitialized = false;
        private static MessageProviderCollection _providers = null;
        private static MessageProvider _provider = null;

        /// <summary>
        /// 静态构造函数,初始化
        /// </summary>
        static Message()
        {
            Initialize();
        }

        /// <summary>
        /// 插入信息
        /// </summary>
        /// <param name="mm">Message实体对象</param>
        /// <returns></returns>
        public static bool Insert(MessageModel mm)
        {
            return _provider.Insert(mm);
        }

        /// <summary>
        /// 获取信息
        /// </summary>
        /// <returns></returns>
        public static List<MessageModel> Get()
        {
            return _provider.Get();
        }

        private static void Initialize()
        {
            try
            {
                MessageProviderConfigurationSection messageConfig = null;

                if (!m_isInitialized)
                {

                    // 找到配置文件中“MessageProvider”节点
                    messageConfig = (MessageProviderConfigurationSection)ConfigurationManager.GetSection("MessageProvider");

                    if (messageConfig == null)
                        throw new ConfigurationErrorsException("在配置文件中没找到“MessageProvider”节点");

                    _providers = new MessageProviderCollection();

                    // 使用System.Web.Configuration.ProvidersHelper类调用每个Provider的Initialize()方法
                    ProvidersHelper.InstantiateProviders(messageConfig.Providers, _providers, typeof(MessageProvider));

                    // 所用的Provider为配置中默认的Provider
                    _provider = _providers[messageConfig.DefaultProvider] as MessageProvider;

                    m_isInitialized = true;

                }
            }
            catch (Exception ex)
            {
                string msg = ex.Message;
                throw new Exception(msg);
            }
        }

        private static MessageProvider Provider
        {
            get
            {
                return _provider;
            }
        }

        private static MessageProviderCollection Providers
        {
            get
            {
                return _providers;
            }
        }
    }
}

Web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="MessageProvider" type="Pattern.Provider.MessageProviderConfigurationSection, Pattern.Provider" />
  </configSections>
  <MessageProvider defaultProvider="SqlMessageProvider">
    <providers>
      <add name="XmlMessageProvider" type="Pattern.Provider.XmlMessageProvider, Pattern.Provider" connectionStringName="XmlConnection" />
      <add name="SqlMessageProvider" type="Pattern.Provider.SqlMessageProvider, Pattern.Provider" connectionStringName="SqlConnection" />
    </providers>
  </MessageProvider>
  <connectionStrings>
    <add name="SqlConnection" connectionString="server=.;database=db;uid=sa;pwd=sa" />
    <add name="XmlConnection" connectionString="XmlPath" />
  </connectionStrings>
</configuration>

Test

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using Pattern.Provider;

public partial class Provider : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.Write(Message.Insert(new MessageModel("插入", DateTime.Now)));
        Response.Write("<br />");
        Response.Write(Message.Get()[0].Message + " " + Message.Get()[0].PublishTime.ToString());
    }
}

运行结果
True
SQL方式,连接字符串是server=.;database=db;uid=sa;pwd=sa 2007-1-22 8:21:44

OK
[源码下载]

打造属于你的提供者(Provider = Strategy + Factory Method) 设计模式 - Provider Pattern(提供者模式)的更多相关文章

  1. 工厂方法模式(Factory Method)和抽象工厂模式(Abstact Factory)

    分类 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的.工厂模式在<Java 与模式>中分为三类:1)简单工厂模式(Simple Facto ...

  2. 抽象工厂(Abstract Factory),工厂方法(Factory Method),单例模式(Singleton Pattern)

    在谈工厂之前,先阐述一个观点:那就是在实际程序设计中,为了设计灵活的多态代码,代码中尽量不使用new去实例化一个对象,那么不使用new去实例化对象,剩下可用的方法就可以选择使用工厂方法,原型复制等去实 ...

  3. 设计模式之简单工厂模式Simple Factory(四创建型)

    工厂模式简介. 工厂模式专门负责将大量有共同接口的类实例化 工厂模式可以动态决定将哪一个类实例化,不必事先知道每次要实例化哪一个类. 工厂模式有三种形态: 1.简单工厂模式Simple Factory ...

  4. Java设计模式-工厂方法模式(Factory Method)

    工厂方法模式(Factory Method) 工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建.在以下的三种模式中,第一种如果传入的字符串有误,不能正确创 ...

  5. Factory Method模式

    Factory Method(工厂方法)模式属于GoF设计模式中的创建型分组,它用于在不之制定待创建对象的具体类的情况下创建对象.--<asp.net设计模式> 说白了就是一个人想要出国旅 ...

  6. Factory Method (工厂模式)

    什么是工厂设计模式 根据名字即可了解,工厂肯定是用来生产产品的,在我们的程序开发中,需要用到不同的类,对于熟悉SSH.SSM开发的可以知道,在初期学习的时候,总是有一个框架提供好的的factory供我 ...

  7. 设计模式之笔记--工厂方法模式(Factory Method)

    工厂方法模式(Factory Method) 定义 工厂方法模式(Factory Method),定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 类图 描 ...

  8. Provider Pattern提供者模式和策略模式

    http://www.codeproject.com/Articles/18222/Provider-Pattern Introduction Provider pattern is one of t ...

  9. angularjs中provider,factory,service的区别和用法

    angularjs中provider,factory,service的区别和用法 都能提供service,但是又有差别 service 第一次被注入时实例化,只实例化一次,整个应用的生命周期中是个单例 ...

随机推荐

  1. js面向对象杂谈

    **万丈高楼平地起** 1. 通过命名规范创建具有私有属性的对象: 以__开头的对象为私有对象,但是实际是能访问到的. 2. 通过自执行函数中,return出来一个对象,return旁边的地方都可以写 ...

  2. Scrapy的中间件(一)

    中间件是Scrapy里面的一个核心概念.使用中间件可以在爬虫的请求发起之前或者请求返回之后对数据进行定制化修改,从而开发出适应不同情况的爬虫. "中间件"这个中文名字和前面章节讲到 ...

  3. 关于sg函数的一些证明

    复习csp2019的时候稍微看了看博弈论,发现自己对于sg函数的理解完全不到位 有些定义甚至想都没想过 于是就口胡了一篇blog来安慰虚弱的自己 Question 1 对于一个满足拓扑性质的公平组合游 ...

  4. java web开发入门一(servlet和jsp)基于eclispe

    servlet 用java语言开发动态资源网站的技术,在doGet方法中拼接显示html,在doPost方法中提交数据.类似于.net的ashx技术. servlet生成的class文件存放在tomc ...

  5. Spring Boot进阶系列二

    上一篇文章,主要分析了怎么建立一个Restful web service,系列二主要创建一个H5静态页面使用ajax请求数据,功能主要有添加一本书,请求所有书并且按照Id降序排列,以及查看,删除一本书 ...

  6. libevent笔记4:Filter_bufferevent过滤器

    Filter_bufferevent是一种基于bufferevent的过滤器,其本身也是一个bufferevent.能够对底层bufferevent输入缓存区中的数据进行操作(加/解密等)后再读取,同 ...

  7. .netcore使用MimeKit发送邮件

    以163邮箱为例,借助MimeKit nuget安装:MimeKit类库,源码地址:https://github.com/jstedfast/MimeKit 发送方法如下: #region 邮件发送 ...

  8. JDBC链接数据库MySQL 8.0 Public Key Retrieval is not allowed 错误的解决方法

    现象 Mybatis和Spring框架整合过程中报 com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Publ ...

  9. [转帖]聊聊Web App、Hybrid App与Native App的设计差异

    聊聊Web App.Hybrid App与Native App的设计差异 https://www.cnblogs.com/zhuiluoyu/p/6056672.html 编者按:这3类主流应用你都了 ...

  10. python 实例

    进度条 import sys, time class ShowProcess(object): """ 显示处理进度的类 调用该类相关函数即可实现处理进度的显示 &quo ...