syuko

Just For Fun。生存,社会秩序,娱乐
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

abstract,virtual,static和工厂的使用问题。

Posted on 2007-11-12 21:35  syuko  阅读(3025)  评论(28)    收藏  举报

   我们做项目的时候几乎每个项目都会有代码表(只有键和值两个字段的数据表),很多代码表都是需要维护的,如果我们每个都从新开始编码那将浪费大量时间。我今天有空就写了一个小的解决方案,但发现了大量的问题,下面一一讲述:
    先假设有单位表(表名:DanWei,PK:ID,ValueField:Name),职位表(表名:ZhiWei,PK:ID,ValueField:Name),职称表(表名:ZhiCheng,PK:ID,ValueField:Name),他们都需要进行增删改的操作。当然有时候一个项目有上十个或更多的代码表需要维护。
    这个示例是WebForm采用了3层架构。数据层为:DataAccess,业务层为:DataBusiness,表现层为:WebProject。
    我先写了一个代码表操作的基类,代码如下:

  1/// <summary>
  2    /// 只有键、值两个字段的数据维护的基类。只能被继承,不能实例化
  3    /// </summary>

  4    public abstract class clsDictCodeBase : ClassBase
  5    {
  6        属性
 47
 48        /// <summary>
 49        /// 通过ID更新记录
 50        /// </summary>
 51        /// <param name="ID">主键</param>
 52        /// <param name="NameValue">更新后的值</param>

 53        public virtual void UpdateRecordByID(int ID, string NameValue)
 54        {
 55            try
 56            {
 57                dbCtrl.cmd_Execute("Update " + TableName + " set " + ValueField + "=@NameValue where " + PKField + "=" + ID
 58                , new SqlParameter("@NameValue", NameValue));
 59            }

 60            catch (Exception ex)
 61            {
 62                throw ex;
 63            }

 64        }

 65
 66        /// <summary>
 67        /// 通过ID删除一条记录
 68        /// </summary>
 69        /// <param name="ID">要删除的ID</param>

 70        public virtual void DeleteRecordByID(int ID)
 71        {
 72            try
 73            {
 74                dbCtrl.cmd_Execute("Delete from  " + TableName + " where " + PKField + "=" + ID);
 75            }

 76            catch (Exception ex)
 77            {
 78                throw ex;
 79            }

 80        }

 81
 82        /// <summary>
 83        /// 插入一条记录
 84        /// </summary>
 85        /// <param name="Name"></param>

 86        public virtual void InsertRecord(string Name)
 87        {
 88            try
 89            {
 90                dbCtrl.cmd_Execute("Insert into " + TableName + "(" + ValueField + ") values(@ValueName)",
 91                    new SqlParameter("@ValueName", Name));
 92            }

 93            catch (Exception ex)
 94            {
 95                throw ex;
 96            }

 97
 98        }

 99
100        /// <summary>
101        /// 通过ID选出一条记录
102        /// </summary>
103        /// <param name="ID">主键</param>

104        public virtual System.Data.DataTable SelectByID(int ID)
105        {
106            try
107            {
108                return (DataTable)dbCtrl.get_DataTable("select * from " + TableName + " where ID=" + ID);
109            }

110            catch (Exception ex)
111            {
112                throw ex;
113            }

114        }

115
116        /// <summary>
117        /// 通过Name选出记录
118        /// </summary>
119        /// <param name="Name">Name</param>

120        public virtual System.Data.DataTable SelectByName(string Name)
121        {
122            try
123            {
124                return (DataTable)dbCtrl.get_DataTable("select * from " + TableName + " where " + ValueField + " like '%'@Name'%' order by " + PKField + " desc",
125                new SqlParameter("@Name", Name));
126            }

127            catch (Exception ex)
128            {
129
130                throw ex;
131            }

132        }

133
134        /// <summary>
135        /// 选出所有记录
136        /// </summary>

137        public virtual System.Data.DataTable SelectAll()
138        {
139            try
140            {
141                return (DataTable)dbCtrl.get_DataTable("select * from " + TableName + " order by " + PKField + " desc");
142            }

143            catch (Exception ex)
144            {
145                throw ex;
146            }

147        }

148
149    }

    其中这个类是个抽象类,里面都是虚方法和属性,将这个类写成虚类就是防止用户在表现层里实例化。这里面将要操作的表名和字段名写成了虚属性,以便通用。
    现在写了一个单位的代码表维护类,类似于这样的类的个数依数据表的个数而定,现只贴出一个示例。代码如下:
   
 1/// <summary>
 2    /// 单位代码表管理的业务类
 3    /// </summary>

 4    public class clsSocietiesMng : clsDictCodeBase
 5    {
 6        public clsSocietiesMng()
 7        {
 8        }

 9
10        /// <summary>
11        /// 通过ID更新一条社团记录
12        /// </summary>
13        /// <param name="ID">主键</param>
14        /// <param name="NameValue">更新后的值</param>

15        public void UpdateSocietyByID(int ID, string NameValue)
16        {
17            try
18            {
19                UpdateRecordByID(ID, NameValue);
20            }

21            catch (Exception ex)
22            {
23                throw ex;
24            }

25        }

26        
27        /// <summary>
28        /// 通过ID删除一条社团记录
29        /// </summary>
30        /// <param name="ID">要删除的ID</param>

31        public void DeleteSocietyByID(int ID)
32        {
33            try
34            {
35                DeleteRecordByID(ID);
36            }

37            catch (Exception ex)
38            {
39                throw ex;
40            }

41        }

42
43        /// <summary>
44        /// 插入一条社团记录
45        /// </summary>
46        /// <param name="Name"></param>

47        public void InsertSociety(string Name)
48        {
49            try
50            {
51                InsertRecord(Name);
52            }

53            catch (Exception ex)
54            {
55                throw ex;
56            }

57
58        }

59    }
    这个类继承自上面所写的代码表操作的基类,但并没有override其中的Virtual方法,因为这里没必要override,同时新增了3个方法。我本想将这个类也写成
抽象类的,但是如果那样做了就没办法实例化了,这是个问题,下面将会提到。我确实不想这个类被用户在表现层实例化,因为这个类里面涉及到了表名和字段名。所以我打算写一个工厂类去实例化它们。
    工厂类代码如下:
   
 1代码表名称的枚举
17
18        /// <summary>
19        /// 创建clsSocietiesMng的实例
20        /// </summary>
21        /// <returns></returns>

22        public static clsSocietiesMng CreateSociety()
23        {
24            string strClassName = _strSocietyPath + ".clsSocietiesMng";
25
26            clsSocietiesMng codeOperator = (clsSocietiesMng)Assembly.Load(_strSocietyPath).CreateInstance(strClassName);
27            codeOperator.TableName = "DanWei";
28            codeOperator.PKField = "DanWeiID";
29            codeOperator.ValueField = "DanWei";
30
31            return codeOperator;
32        }

33    }
    这个类现在不能说是一个工厂,待会我就说为什么我没有将其写成一个工厂类。这个类负责去实例化上述那些代码表操作类,同时给数据表名,字段名属性赋值,防止在表现层出现数据表名和字段名等。
    但由于我的这些代码表操作类都没有继承自一个统一的接口所以不能用一个工厂方法去自动实例化这些类,而必须去一个一个地写成方法。
    这样写成3个类后用户在表现层如下使用:
   
1clsSocietiesMng society = clsDictCodeControl.CreateSociety();
2society.UpdateRecordByID(1,"aaa'aaa");
    虽然如第一行所示,可以采用clsDictCodeControl.CreateSociety();方法去实例化一个实例,但是用户同样可以直接clsSocietiesMng society = new clsSocietiesMng();去实例化一个实例,我不想让用户直接在表现层通过clsSocietiesMng society = new clsSocietiesMng();去实例化。我想将clsSocietiesMng之类的处理类写成抽象类但是那样不行,这个问题还真不知道怎么去解决呢。
    处理类这样写让我觉得有些问题解决的不好:
    1 用户在表现层同样可以自己去实例化(例如:clsSocietiesMng society = new clsSocietiesMng())而不用实例方法(clsDictCodeControl.CreateSociety();)。这点让我决得很不好,但我不知道怎么去解决。
    2 这个工厂类应该变成一个真正的简单工厂类,而不是现在的这个样子。
    以上两个问题是我觉得最严重的问题。当然这个方案里面还存在这其它的问题就不一一列举了,我这里给出我的解决方案只是起一个抛砖引玉的作用,希望大家能提出更好的解决方案。