从题库封装理解抽象类,继承和接口

思路:

  方案一:在策略模式+反射这篇博客里面我们说道为了封装题库,D层写了一个抽象类,包括题型的所有方法,子类重写父类的方法。然后再B层利用反射找到D层的具体题型。具体实现可以参考上篇博客,在这里就不在赘述。这样实现就有一个问题,比如所有的题型都需要生成相同的答题记录表,这样每个子类都需要重写父类的方法,造成大量的代码冗余。

  方案二:采用继承,将公共的方法放到父类里面,子类继承父类同时拥有自己新的方法。在接口层写一个公共的接口,包括所有的方法。这样我们就可以将一些共同的方法都放到父类里面,即使有的题型需要的方法体不同,只要把父类的方法定义为virtual类型的,在子类里面重写一下就可以了。说的有点乱,下面来看代码:

///
//  QuestionManageBLL.cs
//作者: 王永俊
//小组:提高班-考试系统3.0版-教师端
//说明:试题抽象工厂+反射——策略模式
//创建日期:4-11月-2013 20:15:14
//版本号:
///
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using IDAL;
namespace QuestionManageBLL
{
    //调用这个类时,QuestionType和TableName是必须传的参数(及题型Value值和数据库表名)
   public class QuestionContextBLL
    {
        //获取程序集名称
        private static readonly string AssemblyName = "QuestionManageDAL";
        //实例化一个试题公共对象
        IQuestionCommonDAL question = null;

        /// <summary>
        ///反射到QuestionManagerDAL里面的类
        /// </summary>
        /// <param name="QuestionType">题型Value值</param>
       
        //利用反射取得具体的题型
        public QuestionContextBLL(Hashtable map)
        {
            string className = AssemblyName + "." + map["QuestionType"].ToString() + "DAL";

            question = (IQuestionCommonDAL)Assembly.Load(AssemblyName).CreateInstance(className);


        }
        /// <summary>
        ///二次登陆
        /// </summary>
        /// <param name="TableName">表名</param>
        /// <param name="TableNameRecord">答题记录表名</param>
        /// <param name="StudentID">学号</param>
        /// <param name="ExamID">考试ID</param>
        public DataTable GetTestExamResult(Hashtable map)
        {
            return question.GetTestExam(map);
        }
        /// <summary>
        ///创建题型表
        /// </summary>
        /// <param name="TableName">表名</param>
        public bool CreateQuestionTable(Hashtable map)
        {
            return question.CreateQuestionTable(map);
        }
        /// <summary>
        /// 是否存在该记录
        /// </summary>
        /// <param name="TableName">表名</param>
        /// <param name="QuestionContent">题干</param>
        public bool ExistQuestion(Hashtable map)
        {
            return question.ExistQuestion(map);
        }
///
// IQuestionManageDAL.cs
//作者: 王永俊
//小组:提高班-考试系统3.0版-教师端
//说明:试题公共类——接口
//创建日期:3-11月-2013 20:15:14
//版本号:1.0
///
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Collections;
namespace IDAL
{
    public interface IQuestionCommonDAL
    {
        /// <summary>
        ///二次登陆
        /// </summary>
        /// <returns></returns>
        DataTable GetTestExam(Hashtable map);

        /// <summary>
        /// 根据章节查询题库信息
        /// </summary>
        DataTable SelectQuestionbyChapter(Hashtable map);


        /// <summary>
        /// 根据是否可用查询题库信息
        /// </summary>
        DataTable SelectQuestionbyIsvalid(Hashtable map);
//
// QuestionCommonDAL.cs
//作者: 王永俊
//小组:提高班-考试系统3.0版-教师端
//说明:试题公共类——父类
//创建日期:3-11月-2013 20:15:14
//版本号:1.0
///
using System;
using System.Data;
using System.Text;
using System.Data.SqlClient;
using DBUtility;//Please add references
using System.Collections;
using IDAL;
namespace SQLServerDAL
{
    //试题父类,一些公共方法!
  public class QuestionCommonDAL
    {
        /// <summary>
        ///二次登陆
        /// </summary>
        /// <returns></returns>
        public virtual DataTable GetTestExam(Hashtable map)
        {
                      DataTable dt;
                              string strSql = "SELECT j.*,t.EXAMANSWER FROM " + map["TableNameRecord"].ToString() + " t inner join " + map["TableName"].ToString() + " j On j.QuestionID=t.QuestionID WHERE t.StudentID=@StudentID and  ExamID=@ExamID";//and j.Degree=@Degree";
                SqlParameter[] parameters = {
			new SqlParameter("@StudentID", map["StudentID"].ToString ()),
            new SqlParameter("@ExamID", map["ExamID"].ToString ())};
                dt = DbHelperSQL.Query(strSql.ToString(),parameters ).Tables[0];
                return dt;
        }
 /// <summary>
        /// 题库中是否存在该记录
        /// </summary>
        public bool ExistQuestion(Hashtable map)
        {
            StringBuilder strSql = new StringBuilder();
            strSql.Append("select count(1) from " + map["TableName"].ToString());
            strSql.Append(" where QuestionContent=@QuestionContent ");
            SqlParameter[] parameters = {
					new SqlParameter("@QuestionContent", map["QuestionContent"].ToString())};
            bool a= DbHelperSQL.Exists(strSql.ToString(), parameters);
            return a;
        }

        /// <summary>
        /// 根据章节查询题库信息
        /// </summary>
        public virtual DataTable SelectQuestionbyChapter(Hashtable map)
        {
                         DataTable dt;
                StringBuilder strSql = new StringBuilder();
                strSql.Append("select [QuestionID] as '题号' ,[ChapterID] as '章节',[QuestionTypeID] as  '题型',[Degree] as '难度等级',[Fraction] as '总分值',[QuestionContent] as '主题干',[CorrectAnswer] as '标准答案',[IsValid] as '有效性',[Remark] as '备注'");
                strSql.Append(" FROM  " + map["TableName"].ToString());
                strSql.Append(" where ChapterID=@ChapterID order by QuestionID");
                SqlParameter[] parameters = {
					new SqlParameter("@ChapterID",map["ChapterID"].ToString () )};
                dt = DbHelperSQL.Query(strSql.ToString(),parameters ).Tables[0];
                return dt;
        }
        /// <summary>
        /// 根据试题ID查询题库信息
        /// </summary>
        public virtual DataTable SelectQuestionbyQuestionID(Hashtable map)
        {
            try
            {
                DataTable dt;
                StringBuilder strSql = new StringBuilder();
                strSql.Append("select [QuestionID]  ,[ChapterID] ,[QuestionTypeID] ,[Degree] ,[Fraction] ,[QuestionContent] ,[CorrectAnswer],[IsValid] ,[Remark] ");
                strSql.Append(" FROM  " + map["TableName"].ToString());
                strSql.Append(" where ");
                if (map["QuestionID"].ToString() != "")
                { strSql.Append(" QuestionID=@QuestionID and "); }
                if (map["IsValid"].ToString() != "")
                { strSql.Append("IsValid=@IsValid "); }
                strSql.Append(" order by QuestionID");
                SqlParameter[] parameters = {
				new SqlParameter("@QuestionID", map["QuestionID"].ToString ()),
                new SqlParameter("@IsValid", map["IsValid"].ToString ())};
                dt = DbHelperSQL.Query(strSql.ToString(),parameters ).Tables[0];
                return dt;
            }
            finally
            {

            }
        }
///
//  ClozeDAL.cs
//作者: 王永俊
//小组:提高班-考试系统3.0版-教师端
//说明:完型填空
//创建日期:3-11月-2013 20:15:14
//版本号:1.0
///
using System;
using System.Data;
using System.Text;
using System.Data.SqlClient;
using DBUtility;//Please add references
using System.Collections;
using IDAL;
using SQLServerDAL;
namespace QuestionManageDAL
{
    public class ClozeDAL : QuestionCommonDAL, IQuestionCommonDAL
    {
        #region  BasicMethod

        /// <summary>
        /// 根据课程创建完型填空题表
        /// </summary>
        /// <param name="courseName">哈希表</param>
        public bool CreateQuestionTable(Hashtable map)
        {
            try
            {
                //创建主表
                string strSql = @"IF object_id('" + map["TableName"].ToString() + "') IS NULL Create Table " + map["TableName"].ToString() + "(QuestionID int, " +
                     "Scope varchar(20) ," +
                     "BookName varchar(20) ," +
                     "ChapterID varchar(20) ," +
                      "QuestionTypeID varchar(20)," +
                      "Degree int," +
                      "Fraction float," +
                      "QuestionContent varchar(Max)," +
                      "IsValid varchar(10)  ," +
                      "AddUser varchar(20)," +
                      "Timestamp varchar(20)," +
                      "Remark varchar(Max)," +
                      "Other1 varchar(50)," +
                      "Other2 varchar(50) constraint PK_" + map["TableName"].ToString() + " primary key (QuestionID))";
                int rows = DbHelperSQL.ExecuteSql(strSql.ToString());
                //创建从表
                string strSql1 = " Create Table " + map["TableName"].ToString() + "_Detail " + "(ID int IDENTITY(1,1)," +
                    "QuestionID int ," +
                    "QuestionNo int ," +
                     "Score float ," +

                     "Answer1 varchar(Max)," +
                     "Answer2 varchar(Max)," +
                     "Answer3 varchar(Max)," +
                     "Answer4 varchar(Max)," +
                     "CorrectAnswer varchar(Max)," +

                     "Other1 varchar(50)," +
                     "Other2 varchar(50) constraint PK_" + map["TableName"].ToString() + "_Detail " + " primary key (ID))";
                int rows1 = DbHelperSQL.ExecuteSql(strSql1.ToString());
                if (rows != 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            finally
            {
            }
        }
   /// <summary>
        ///二次登陆
        /// </summary>
        /// <returns></returns>
        public override DataTable GetTestExam(Hashtable map)
        {
            try
            {
                DataTable dt;

                string strSql = "SELECT m.*, j.*,t.EXAMANSWER FROM " + map["TableNameRecord"].ToString() + " t inner join " + map["TableName"].ToString() + "_Detail " + "j On j.ID=t.QuestionID inner join " + map["TableName"].ToString() + " m On m.QuestionID=j.QuestionID WHERE t.StudentID=@StudentID and  ExamID=@ExamID";//and j.Degree=@Degree";
                SqlParameter[] parameters = {
					new SqlParameter("@StudentID", map["StudentID"].ToString ()),
                    new SqlParameter("@ExamID", map["ExamID"].ToString ())};
                dt = DbHelperSQL.Query(strSql.ToString(), parameters).Tables[0];
                return dt;

            }
            finally
            {

            }

        }
        #endregion  BasicMethod
    }
}

讲解:

         QuestionManageBLL层基本上没有变化,只是通过接口反射。IQuestionCommonDAL

定义方法的规则,必须包括所有的方法。父类QuestionCommonDAL包括所有题型共有

的方法,比如:对题库的所有操作。以及大部分题型共有的方法,其他题型只需要重写父

类的方法。这样可以大量的减少代码的重复性。具体题型ClozeDAL类,继

QuestionCommonDAL同时实现接口 IQuestionCommonDAL。他既有自己的新方

CreateQuestionTable也继承了父类的ExistQuestion方法,重写了GetTestExam方法。这

样就让整个题库更加的内聚而对外更加灵活。比如需要添加一些共同的方法,直接添加

到父类就行。而子类里面不用更改。

总结:

    对整个封装是一步步的完善的,也更好的理解了抽象类和继承以及接口。抽象类是

为了实现代码的复用和管理,体现OOP的继承特性,子类都有相同的方法,并且方法体

都不同可以选择抽象类。普通类的继承可以精炼你的代码,提高代码的复用。并且提高

整个系统的灵活性。而接口其实就是为我们的D层类订了一个规范,所有的子类都要按

照这个规范来,体现多态的思想。总体来说:当你写的新类和已有的类很相似时就用抽

象类,在很多类很相似时就给他们加一个相同的父类,其实抽象类及接口本质上都是父

类。

问题:

     现在基本功能实现了,可是这样有个问题就是只要添加新的题型,无论他和以前的题

型多么相似,我都需要给它添加一个新类,进行封装。


评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值