文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>【实战设计模式】01.模板方法模式

【实战设计模式】01.模板方法模式

时间:2011-03-22  来源:lovebabii

在这一篇里,会实现简单的数据库操作操作组件,首先要确定的是,数据库操作模块是与业务无关的。

  首先,在基于数据库的项目里,我们都会有数据库访问代码,对于不同的数据库,如SqlServer 我们会用到主要的类SqlConnection,SqlDataAdapter,SqlCommand等对象;对于Oracle,同样有OracleConnection,OracleDataAdapter等。

  很明显,我们会发现这些类会有相同的接口,IDbConnection,IDbCommand,IDbDataAdapter,而访问数据库的流程,或者说是调用这些对象的过程是
相似的,这些正是我们要找的共同点之一,

  (using IDbConnection conn = ??)
  {
      conn.open();
      IDbCommand = command = conn.CreateCommand();
      ...   
  }

  为了提高代码的重用,很容易想到,通过面向对象的继承的方式,来实现不同的数据库访问组件,共同点由基类实现,不同的部分由子类实现,正是面
向对象多态的体现,不是吗。到现在为止,我们已经可以编写部分的代码,从开始分析道现在,我们并没有想到要如何用何种设计模式,很自然的想到的
只是面向对象的编程方式:继承,多态。

  1.类图结构,


  很明显,基类DbClient有3个protected abstract方法,为什么是protected的,因为这几个方法不需要提供给外部使用,而是子类实现,供基类DbClient内部调用, 这样,体现了封装,不是么。

  2.为了简单明了,这里在基类里只提供一个公共方法ExecuteData(),通过对几个abstract方法的调用,实现对数据访问的流程代码。见如下代码:

View Code
 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Data;
6
7 namespace Babii.Practices.Core.DesignPatterns.TemplateMethod
8 {
9 /// <summary>
10 /// 数据库操作类基类
11 /// </summary>
12 public abstract class DbClient
13 {
14 //抽象方法
15 protected abstract IDbCommand CreateDbCommand();
16
17 //抽象方法
18 protected abstract IDbDataAdapter CreateDbDataAdapter(IDbCommand command);
19
20 //抽象方法
21 protected abstract IDbDataParameter CreateDataParameter(string name, object value);
22
23 //模板方法
24 public DataTable ExecuteData(string query, Dictionary<string, object> parameters)
25 {
26 IDbCommand command = CreateDbCommand(); //调用抽象方法
27 command.CommandType = CommandType.Text;
28 command.CommandText = query;
29
30 foreach (var paramPair in parameters)
31 {
32 IDbDataParameter param = null;
33
34 param = CreateDataParameter(paramPair.Key, paramPair.Value);//调用抽象方法
35
36
37 if (param.Value == null)
38 param.Value = DBNull.Value;
39
40 command.Parameters.Add(param);
41 }
42
43 IDbDataAdapter adapter = CreateDbDataAdapter(command);//调用抽象方法
44 DataSet data = new DataSet();
45
46 try
47 {
48 adapter.Fill(data);
49 }
50 catch (Exception err)
51 {
52 throw new Exception(err.Message + Environment.NewLine + "query : " + query);
53 }
54
55 if (data.Tables.Count > 0)
56 return data.Tables[data.Tables.Count - 1];
57
58 return null;
59 }
60 }
61 }

  到此,我们很自然的在实现基类的代码,好了,切入正题,引入设计模式,  

  模板方法Template Method模式:

    提供算法骨架的设计。它支持开发者还没有定义算法如何实现的情况下,定义处理流程和协调逻辑。

  基类DbClient的ExecuteData内部的实现就是“提供算法骨架的设计,定义处理流程和协调逻辑”的体现。

  3.我们在看看如何实现子类SqlDbClient,

View Code
 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Data;
6 using System.Data.SqlClient;
7
8 namespace Babii.Practices.Core.DesignPatterns.TemplateMethod
9 {
10 public class SqlDbClient : DbClient
11 {
12 private SqlConnection _connection;
13
14 public SqlDbClient(string connectionString)
15 {
16 _connection = new SqlConnection(connectionString);
17 }
18
19 protected override IDbCommand CreateDbCommand()
20 {
21 return _connection.CreateCommand();
22 }
23
24 protected override IDbDataAdapter CreateDbDataAdapter(IDbCommand command)
25 {
26 return new SqlDataAdapter(command as SqlCommand);
27 }
28
29 protected override IDbDataParameter CreateDataParameter(string name, object value)
30 {
31 return new SqlParameter(name, value);
32 }
33 }
34 }

  对于OracleClient,有兴趣的可以动手实现一些,要注意的,我们以Oracle官方的ODP.NET提供的组件为基础来实现.

  4.自此,主体结构已经很明显了,此时,有几点需要再理解,
<1>DbClient基类中,3个抽象方法,更像是占位符,也可以称为钩子方法,具体的实现延后到子类。基类中的模板方法ExcuteData()内部,调用抽象方

法的流程是固定的,也就是说是hard code,这或许是我们不愿意看到的,但目前没有问题。
<2>“不要调用我,我来调用你”这是好莱坞原则。在这里,这个原则是说DbClient中的模板方法调用了子类SqlDbClient的几个Override方法,而不是

DbClient调用SqlDbClient, 更不是父类控制子类。实际上,要调用DbClient,我们需要先创建SqlDbClient的实例。


  5.对于模板方法模式的学习和理解就暂时到这里,对DbClient的功能可以不断完善,在实际项目中不断的应用和总结,发现问题和解决问题,这是我们所希

望的,因为,设计模式不是银弹,还有相当的问题需要我们权衡后解决。


Src download
注:有任何问题和错误的地方,请您指教,谢谢。

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载