好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

.NET简谈策略模式

.NET简谈策略模式

策略模式在我们日常开发中经常被用到,这篇文章不是策略模式的深入讨论和学术研究,只是让初学者能有个基本的了解。

什么叫策略 :1. 可以实现目标的方案集合;2. 根据形势发展而制定的行动方针和斗争方法;3. 有斗争艺术,能注意方式方法。

什么叫模式: 模式(Pattern)其实就是解决某一类问题的方法论。把解决某类问题的方法总结归纳到理论高度,那就是模式。模式是一种指导,在一个良好的指导下,有助于你完成任务,有助于你作出一个优良的设计方案,达到事半功倍的效果。而且会得到解决问题的最佳办法。

什么叫策略模式 :策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

从上面的官方解释来看,我们已经有了一个基本的雏形。其实设计模式就是前辈们所总结出来的,用来解决某类问题的方法论;这些方法论是经过身经百战的专家们提炼出来的,比较规范的、比较科学的模型。 [王清培版权所有,转载请给出署名]

其实设计模式对初学者来说可能有点头疼,比较抽象。大概就是因为初学者对一些概念不能深度的理解,一些理论知识还没能够融会贯通,不过不要紧经过一段时间的实践锻炼就能理解了;下面我们循环渐进的来讲解什么叫策略模式。我们拿真实项目中遇到的问题来讲解吧,这样能更好的吸引注意力。

情景引入:

您是否遇到过这样一个头疼的问题,在我们开发信息系统的时候,经常需要切换不同的数据库。但是由于我们前期开发项目的时候没有考虑到后期的变更,所以这个时候问题就来了。如果需要更换数据库,将大动干戈把代码翻个底朝天。将诸如一些Sql、Oledb、Oracle之类的对象进行全局替换。这样的设计永远都无法满足日后的数据库变更需求。所以在前期设计的时候,我们就需要考虑到系统后期可能存在哪些可能变化的地方,在系统的架构上就需要变通设计(比如:依赖接口而不是具体的对象,通过依赖注入等方式进行策略的变更;)。其实这个时候我们很需要一种模式能解决此类问题,恰好前辈们为我们准备好了(策略模式)。 [设计模式的设计原则:尽可能的考虑系统后期的变化;]

1.没有分析之前的系统结构:

 情景分析:

我们暂且不谈设计模式,我们试着自己分析一下问题。我们需要一种机制,能在需要的时候自动变更后台数据源的连接对象;我们来收集问题,既然要自动变更后台数据源连接对象,那么我们在编码的过程中就不能直接使用一些诸如SqlConnection、SqlCommand等对象,必须进行提取形成接口,消除类之间的强耦合 。[面向对象编程原则:面向接口编程,而不是面向实现编程;]

2.分析之后的系统结构图:

情景分析->接口提取:

/*----------------------------------------------------------------

  * 作者:王清培

  * 时间:2010-10-29

  * ----------------------------------------------------------------*/

using   System;

using   System.Collections.Generic;

using   System.Text;

using   System.Data;

using   System.Data.SqlClient;

 

namespace   W.Data

{

     /// <summary>

     /// 通用数据源类型接口,

     /// 确定每种数据源必须实现基本的对IDbConnection,IDbCommand,IDbTransaction 三者的包装;

     /// </summary>

     public   interface   IDataSourceType

     {

         #region 属性

         /// <summary>

         /// 获取或设置数据源连接字符串。

         /// </summary>

         string   ConnectionString {  get ;  set ; }

         #endregion

         /// <summary>

         /// 开始数据库事务。

         /// </summary>

         void   BeginTransaction();

         /// <summary>

         /// 提交事务处理。

         /// </summary>

         void   Commit();

         /// <summary>

         /// 从挂起状态回滚事务。

         /// </summary>

         void   Rollback();

         /// <summary>

         /// 执行查询,并返回查询所返回的结果集DataSet。

         /// </summary>

         /// <param name="cmdText">要执行的命令文本</param>

         /// <returns>DataSet</returns>

         DataSet ExecuteDataSet( string   commandtext);

         /// <summary>

         /// 执行查询,并返回查询所返回的结果集DataSet。

         /// </summary>

         /// <param name="commandtype"> 指定如何解释命令字符串。</param>

         /// <param name="commandtext">命令文本</param>

         /// <param name="parameter">IDbDataParameter参数列表</param>

         /// <returns>DataSet</returns>

         DataSet ExecuteDataSet(CommandType commandtype,  string   commandtext,  params   IDataParameter[] parameter);

         /// <summary>

         /// 对连接执行 Transact-SQL 语句并返回受影响的行数。

         /// </summary>

         /// <param name="cmdText">命令文本</param>

         /// <returns>受影响的行数</returns>

         int   ExecuteNonQuery( string   cmdText);

         /// <summary>

         /// 对连接执行 Transact-SQL 语句并返回受影响的行数。

         /// </summary>

         /// <param name="commandtype">指定如何解析命令字符串</param>

         /// <param name="commandtext">命令文本</param>

         /// <param name="parameter">IDbDataParameter参数列表</param>

         /// <returns>受影响的行数</returns>

         int   ExecuteNonQuery(CommandType commandtype,  string   commandtext,  params   IDataParameter[] parameter);

         /// <summary>

         /// 对连接执行 Transact-SQL 语句并返回受影响的行数。

         /// </summary>

         /// <param name="conn">IDbConnection对象</param>

         /// <param name="cmdType">指定如何解析命令字符串</param>

         /// <param name="cmdText">命令文本</param>

         /// <param name="commandParameters">IDbDataParameter参数列表</param>

         /// <returns>受影响的行数</returns>

         int   ExecuteNonQuery(IDbConnection conn, CommandType cmdType,  string   cmdText,  params   IDataParameter[] parameter);

         /// <summary>

         ///对连接执行 Transact-SQL 语句并返回受影响的行数。已事务的方式执行

         /// </summary>

         /// <param name="trans">IDbTransaction对象。</param>

         /// <param name="cmdType">指定如何解析命令字符串。</param>

         /// <param name="cmdText">命令文本。</param>

         /// <param name="commandParameters">IDbDataParameter参数列表。</param>

         /// <returns>受影响的行数。</returns>

         int   ExecuteNonQuery(IDbTransaction trans, CommandType cmdType,  string   cmdText,  params   IDataParameter[] parameter);

         /// <summary>

         /// 将 System.Data.SqlClient.SqlCommand.CommandText 发送到

         /// System.Data.SqlClient.SqlCommand.Connection 并生成一个 System.Data.SqlClient.SqlDataReader。

         /// </summary>

         /// <param name="cmdText">执行的命令文本</param>

         /// <returns>IDataReader对象</returns>

         IDataReader ExecuteReader( string   cmdText);

         /// <summary>

         /// 将 System.Data.SqlClient.SqlCommand.CommandText 发送到

         /// System.Data.SqlClient.SqlCommand.Connection 并生成一个 System.Data.SqlClient.SqlDataReader。

         /// </summary>

         /// <param name="cmdType">指定如何解析命令字符串</param>

         /// <param name="cmdText">命令文本</param>

         /// <param name="commandParameters">IDataParameter参数列表</param>

         /// <returns>IDataReader对象</returns>

         IDataReader ExecuteReader(CommandType cmdType,  string   cmdText,  params   IDataParameter[] parameter);

         /// <summary>

         /// 执行查询,并返回查询所返回的结果集中第一行的第一列。忽略其他列或行。

         /// </summary>

         /// <param name="cmdText">命令文本</param>

         /// <returns>结果集中第一行的第一列;如果结果集为空,则为空引用(在 Visual Basic 中为 Nothing)</returns>

         object   ExecuteScalar( string   cmdText);

         /// <summary>

         ///  执行查询,并返回查询所返回的结果集中第一行的第一列。忽略其他列或行。

         /// </summary>

         /// <param name="cmdType">指定如何解析命令字符串</param>

         /// <param name="cmdText">命令文本</param>

         /// <param name="commandParameters">IDataParameter参数列表</param>

         /// <returns>结果集中第一行的第一列;如果结果集为空,则为空引用(在 Visual Basic 中为 Nothing)。</returns>

         object   ExecuteScalar(CommandType cmdType,  string   cmdText,  params   IDataParameter[] parameter);

         /// <summary>

         /// 执行查询,并返回查询所返回的结果集DataTable。

         /// </summary>

         /// <param name="cmdText">命令文本</param>

         /// <returns>DataTable</returns>

         DataTable ExecuteTable( string   cmdText);

         /// <summary>

         ///执行查询,并返回查询所返回的结果集DataTable。

         /// </summary>

         /// <param name="cmdType">指定如何解析命令字符串</param>

         /// <param name="cmdText">命令文本</param>

         /// <param name="commandParameters">IDataParameter参数列表</param>

         /// <returns>DataTable</returns>

         DataTable ExecuteTable(CommandType cmdType,  string   cmdText,  params   IDataParameter[] parameter);

         /// <summary>

         /// 关闭数据库连接。

         /// </summary>

         void   Close();

         /// <summary>

         /// 执行与释放或重置非托管资源相关的应用程序定义的任务。

         /// </summary>

         void   Dispose();

     }

}

情景分析->OLEDB数据源实现:

/*----------------------------------------------------------------

  * 作者:王清培

  * 时间:2010-10-29

  * ----------------------------------------------------------------*/

using   System;

using   System.Collections.Generic;

using   System.Text;

using   System.Configuration;

using   System.Data.OleDb;

using   System.Data;

 

namespace   W.Data

{

     /// <summary>

     /// OLEDB数据源

     /// </summary>

     public   sealed   class   OledbSource : IDataSourceType, IDisposable

     {

         #region 字段

         /// <summary>

         /// 是否已开始数据库事务处理

         /// </summary>

         private   bool   _begin =  false ;

         /// <summary>

         /// IDbConnection对象(包装的SqlConnection对象)

         /// </summary>

         private   OleDbConnection _connection;

         /// <summary>

         /// IDbTransaction对象(包装的SqlTransaction对象)

         /// </summary>

         private   OleDbTransaction _transaction;

         /// <summary>

         /// 静态全局(SQLServerSource数据源)实例连接字符串对象;

         /// </summary>

         private   static   string   _globalconnectionstring =  string .Empty;

 

         #endregion

 

         #region 属性

         /// <summary>

         /// 获取,静态全局SQLServerSource数据源实例连接字符串对象;

         /// </summary>

         public   static   string   GlobalConnectionString

         {

             get   {  return   _globalconnectionstring; }

         }

         /// <summary>

         /// 获取或设置本次执行的数据源的连接字符串

         /// </summary>

         public   string   ConnectionString

         {

             get   {  return   _connection.ConnectionString; }

             set   { _connection.ConnectionString = value; }

         }

         /// <summary>

         /// 获取包装的SqlTransaction对象

         /// </summary>

         public   OleDbTransaction SqlTransaction

         {

             get   {  return   _transaction; }

         }

         #endregion

 

         #region 构造函数

         /// <summary>

         /// 静态构造函数。

         /// </summary>

         static   OledbSource()

         {

             //设置全局(SQLServerSource实例)对象的默认连接字符串

             _globalconnectionstring = ConfigurationManager.ConnectionStrings[ "ConnectionString" ].ConnectionString;

         }

         /// <summary>

         ///默认实例构造函数

         /// </summary>

         public   OledbSource()

         {

             _connection =  new   OleDbConnection(_globalconnectionstring);

         }

         /// <summary>

         /// 重载构造函数,使用指定连接字符串来初始化 CommandLib.Data.SQLServerSource  类的新实例。默认所有的SQLServerSource实例均使用

         /// 配置文件中的SQLServerConnectionString类型的连接字符串。

         /// </summary>

         /// <param name="connectionstring">连接字符串</param>

         public   OledbSource( string   connectionstring)

         {

             _connection =  new   OleDbConnection(connectionstring);

         }

         #endregion

 

         #region 实例方法

         /// <summary>

         /// 开始数据库事务。

         /// </summary>

         public   void   BeginTransaction()

         {

             _begin =  true ;

             _connection.Open();

             _transaction = _connection.BeginTransaction(); //新建数据源的事务对象

         }

         /// <summary>

         /// 提交事务处理。

         /// </summary>

         public   void   Commit()

         {

             _begin =  false ;

             _transaction.Commit();

             _transaction =  null ; //事务执行完毕全部清除(事务不是很常用不需要一直保留)

             _connection.Close();

         }

         /// <summary>

         /// 从挂起状态回滚事务。

         /// </summary>

         public   void   Rollback()

         {

             _begin =  false ;

             _transaction.Rollback();

             _transaction =  null ; //事务执行完毕全部清除(事务不是很常用不需要一直保留)

             _connection.Close();

         }

         /// <summary>

         ///  执行查询,并返回查询所返回的结果集DataSet。

         /// </summary>

         /// <param name="commandtext">命令文本</param>

         /// <returns>DataSet</returns>

         public   DataSet ExecuteDataSet( string   commandtext)

         {

             return   ExecuteDataSet(CommandType.Text, commandtext,  null );

         }

         /// <summary>

         /// 执行查询,并返回查询所返回的结果集DataSet。

         /// </summary>

         /// <param name="commandtype">指定如何解释命令字符串</param>

         /// <param name="commandtext">命令文本</param>

         /// <param name="parameter">IDbDataParameter参数列表</param>

         /// <returns>DataSet</returns>

         public   DataSet ExecuteDataSet(CommandType commandtype,  string   commandtext,  params   IDataParameter[] parameter)

         {

             if   (_connection.State == ConnectionState.Closed)

                 _connection.Open();

             OleDbCommand commmand = InitSqlCommand(commandtype, commandtext, parameter);

             OleDbDataAdapter adapter =  new   OleDbDataAdapter(commmand);

             DataSet ds =  new   DataSet();

             adapter.Fill(ds);

             return   ds;

         }

         /// <summary>

         /// 对连接执行 Transact-SQL 语句并返回受影响的行数。

         /// </summary>

         /// <param name="cmdText">命令文本</param>

         /// <returns>受影响的行数</returns>

         public   int   ExecuteNonQuery( string   cmdText)

         {

             return   ExecuteNonQuery(CommandType.Text, cmdText,  null );

         }

         /// <summary>

         /// 对连接执行 Transact-SQL 语句并返回受影响的行数。

         /// </summary>

         /// <param name="commandtype">IDbConnection对象</param>

         /// <param name="commandtext">指定如何解析命令字符串</param>

         /// <param name="parameter">命令文本</param>

         /// <returns>受影响的行数</returns>

         public   int   ExecuteNonQuery(CommandType commandtype,  string   commandtext,  params   IDataParameter[] parameter)

         {

             if   (_connection.State == ConnectionState.Closed)

                 _connection.Open();

             OleDbCommand command = InitSqlCommand(commandtype, commandtext, parameter);

             return   command.ExecuteNonQuery();

 

         }

         /// <summary>

         /// 重载ExecuteNonQuery方法。

         /// </summary>

         /// <param name="conn">IDbConnection对象</param>

         /// <param name="cmdType">指定如何解析命令字符串</param>

         /// <param name="cmdText">命令文本</param>

         /// <param name="commandParameters">IDbDataParameter参数列表</param>

         /// <returns>受影响的行数</returns>

         public   int   ExecuteNonQuery(IDbConnection conn, CommandType cmdType,  string   cmdText,  params   IDataParameter[] parameter)

         {

             OleDbCommand command = InitSqlCommand(cmdType, cmdText, parameter);

             command.Connection = (conn  as   OleDbConnection);

             return   command.ExecuteNonQuery();

 

         }

         /// <summary>

         /// 重载ExecuteNonQuery方法。以事务的方式执行

         /// </summary>

         /// <param name="trans">IDbTransaction对象。</param>

         /// <param name="cmdType">指定如何解析命令字符串。</param>

         /// <param name="cmdText">命令文本。</param>

         /// <param name="commandParameters">IDbDataParameter参数列表。</param>

         /// <returns>受影响的行数。</returns>

         public   int   ExecuteNonQuery(IDbTransaction trans, CommandType cmdType,  string   cmdText,  params   IDataParameter[] parameter)

         {

             OleDbCommand command = InitSqlCommand(cmdType, cmdText, parameter);

             command.Transaction = (trans  as   OleDbTransaction);

             return   command.ExecuteNonQuery();

         }

         /// <summary>

         /// 将 System.Data.SqlClient.SqlCommand.CommandText 发送到

         /// System.Data.SqlClient.SqlCommand.Connection 并生成一个 System.Data.SqlClient.SqlDataReader。

         /// </summary>

         /// <param name="cmdText">执行的命令文本</param>

         /// <returns>IDataReader对象</returns>

         public   IDataReader ExecuteReader( string   cmdText)

         {

             return   ExecuteReader(CommandType.Text, cmdText,  null );

         }

         /// <summary>

         /// 将 System.Data.SqlClient.SqlCommand.CommandText 发送到

         /// System.Data.SqlClient.SqlCommand.Connection 并生成一个 System.Data.SqlClient.SqlDataReader。

         /// </summary>

         /// <param name="cmdType">指定如何解析命令字符串</param>

         /// <param name="cmdText">命令文本</param>

         /// <param name="commandParameters">IDataParameter参数列表</param>

         /// <returns>IDataReader对象</returns>

         public   IDataReader ExecuteReader(CommandType cmdType,  string   cmdText,  params   IDataParameter[] parameter)

         {

             OleDbCommand command = InitSqlCommand(cmdType, cmdText, parameter);

             return   command.ExecuteReader();

         }

         /// <summary>

         /// 执行查询,并返回查询所返回的结果集中第一行的第一列。忽略其他列或行。

         /// </summary>

         /// <param name="cmdText">命令文本</param>

         /// <returns>结果集中第一行的第一列;如果结果集为空,则为空引用(在 Visual Basic 中为 Nothing)</returns>

         public   object   ExecuteScalar( string   cmdText)

         {

             return   ExecuteScalar(CommandType.Text, cmdText,  null );

         }

         /// <summary>

         ///  执行查询,并返回查询所返回的结果集中第一行的第一列。忽略其他列或行。

         /// </summary>

         /// <param name="cmdType">指定如何解析命令字符串</param>

         /// <param name="cmdText">命令文本</param>

         /// <param name="commandParameters">IDataParameter参数列表</param>

         /// <returns>结果集中第一行的第一列;如果结果集为空,则为空引用(在 Visual Basic 中为 Nothing)。</returns>

         public   object   ExecuteScalar(CommandType cmdType,  string   cmdText,  params   IDataParameter[] parameter)

         {

             OleDbCommand command = InitSqlCommand(cmdType, cmdText, parameter);

             return   command.ExecuteScalar();

         }

         /// <summary>

         /// 执行查询,并返回查询所返回的结果集DataTable。

         /// </summary>

         /// <param name="cmdText">命令文本</param>

         /// <returns>DataTable</returns>

         public   DataTable ExecuteTable( string   cmdText)

         {

             return   ExecuteTable(CommandType.Text, cmdText,  null );

         }

         /// <summary>

         ///执行查询,并返回查询所返回的结果集DataTable。

         /// </summary>

         /// <param name="cmdType">指定如何解析命令字符串</param>

         /// <param name="cmdText">命令文本</param>

         /// <param name="commandParameters">IDataParameter参数列表</param>

         /// <returns>DataTable</returns>

         public   DataTable ExecuteTable(CommandType cmdType,  string   cmdText,  params   IDataParameter[] parameter)

         {

             OleDbCommand command = InitSqlCommand(cmdType, cmdText, parameter);

             DataTable resulttb =  new   DataTable();

             OleDbDataAdapter adapter =  new   OleDbDataAdapter(command);

             adapter.Fill(resulttb);

             return   resulttb;

         }

         /// <summary>

         /// 私有方法实现内部类的SqlCommand的初始化

         /// </summary>

         /// <param name="commandtype">IDbConnection对象</param>

         /// <param name="commandtext">指定如何解析命令字符串</param>

         /// <param name="parameter">命令文本</param>

         /// <returns>SqlCommand</returns>

         private   OleDbCommand InitSqlCommand(CommandType commandtype,  string   commandtext,  params   IDataParameter[] parameter)

         {

             OleDbCommand command =  new   OleDbCommand(commandtext, _connection);

             command.CommandType = commandtype;

             if   (_transaction !=  null )

                 command.Transaction = _transaction;

             if   (parameter !=  null )

                 command.Parameters.AddRange(parameter);

             return   command;

         }

         /// <summary>

         /// 关闭数据库连接。

         /// </summary>

         public   void   Close()

         {

             _connection.Close();

         }

         /// <summary>

         /// 执行与释放或重置非托管资源相关的应用程序定义的任务。

         /// </summary>

         public   void   Dispose()

         {

             _connection.Dispose();

         }

         #endregion

     }

}

这段代码来源我自己的ORM框架中的。我假设实现一个Oledb数据源。但是怎么将对象送给前台调用者呢,方法有很多中可以通过工厂、IOC控制器、策略方法都可以,我是用的工厂实现的;这里我就不贴出代码了,给出调用代码吧,可以完整的结束了;

情景分析->调用代码:

/// <summary>

         ///  根据实体对象和IDataSourceType对象删除一条记录,

         ///  该实体必须明确主键值才能删除记录;如果该实体没有主键可自己编写SQL代码删除;

         /// </summary>

         /// <typeparam name="T">要删除的表对应的实体对象</typeparam>

         /// <param name="t">Model实体</param>

         /// <param name="idatasource">IDataSourceType数据源类型对象</param>

         /// <returns>删除是否成功;1成功,0失败</returns>

         public   static   int   DeleteModelById<T>(T t, IDataSourceType idatasource) where T :  new ()

         {

             string   sqlstring; //保存要执行的T-SQL语句

             List<IDataParameter> paramlist = (List<IDataParameter>)GetDeleteModelParameterT_SQL<T>(t,  out   sqlstring); //获取利用Model删除时的语句和参数列表

             if   (idatasource !=  null )

                 return   idatasource.ExecuteNonQuery(CommandType.Text, sqlstring, paramlist.ToArray());

             return   <span style= "color: #ff0000;" >IDataSourceTypeFactory.Create().ExecuteNonQuery</span>(CommandType.Text, sqlstring, paramlist.ToArray());

         }

总结:调用程序使用接口统一调用数据源不需要关心后台是什么数据源,工厂通过在策略集合中找到合适的策略给调用着;策略模式大概就讲完了,谢谢;

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于.NET简谈策略模式的详细内容...

  阅读:45次