开放-封闭原则:软件实体(类、模块、函数等等)应该可以扩展,但是不可修改。也就是对于扩展开放的,对于更改是封闭的。
学习设计模式的时候对这句话的记忆很深,而且“封装变化”这句话更是记忆深刻,但是也只是记忆深刻,这次做考试系统的时候是真的深刻体会到了。整个考试系统的变化点就是题型,不同的考试会有不同的题型,不同的题型需要不同的字段。这样我们就需要把题型的变化封装起来,当我们添加一个新的题型的时候,尽量不更改原来的系统。初步的设想是将不同的题型的封装到不同DLL文件里面,当需要添加一个题型的时候只需要导入一个DLL文件即可,而不影响其他部分。
以上是需求,我们采用的是策略模式+反射。将各种题型封装成DLL文件,这样就把变化封装起来。
下面看图看代码:
- <span style="font-size:18px">///////////////////////////////////////////////////////////
- // 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 ExamSystemV3.IDAL ;
- //using QuestionManageDAL;
- namespace QuestionManageBLL
- {
- public class QuestionContextBLL
- {
- //获取程序集名称
- private static readonly string AssemblyName = "QuestionManageDAL";
- //实例化一个试题公共对象
- QuestionCommonDAL question = null ;
- //利用反射取得具体的题型
- public QuestionContextBLL(string questionType)
- {
- string className = AssemblyName + "." + questionType + "DAL";
- question = (QuestionCommonDAL)Assembly.Load(AssemblyName).CreateInstance(className);
- }
- /// <summary>
- ///创建题型表
- /// </summary>
- /// <param name="courseName">表名</param>
- public bool CreateTableResult(Hashtable map)
- {
- return question.CreateQuestionTable(map);
- }
- /// <summary>
- /// 增加一条数据
- /// </summary>
- public bool InsertQuestionResult(Hashtable map)
- {
- return question.InsertOneQuestion(map);
- }
- }
- ///////////////////////////////////////////////////////////
- // QuestionManageBLL.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 ExamSystemV3.IDAL
- {
- public abstract class QuestionCommonDAL
- {
- /// <summary>
- /// 根据课程创建选择题表
- /// </summary>
- /// <param name="courseName">哈希表</param>
- public abstract bool CreateQuestionTable(Hashtable map);
- /// <summary>
- /// 增加一条数据
- /// </summary>
- public abstract bool InsertOneQuestion(Hashtable map);
- }
- ///////////////////////////////////////////////////////////
- // QuestionManageDAL.cs
- //作者: 王永俊
- //小组:提高班-考试系统3.0版-教师端
- //说明:试题公共类——策略模式
- //创建日期:3-11月-2013 20:15:14
- //版本号:1.0
- ///////////////////////////////////////////////////////////
- using System;
- using System.Data;
- using System.Text;
- using System.Data.SqlClient;
- using Maticsoft.DBUtility;//Please add references
- using System.Collections;
- using ExamSystemV3.IDAL ;
- namespace QuestionManageDAL
- {
- public class XuanZeTiDAL:QuestionCommonDAL
- {
- //public XuanZeTiDAL()
- // {}
- #region BasicMethod
- /// <summary>
- /// 根据课程创建选择题表
- /// </summary>
- /// <param name="courseName">哈希表</param>
- public override bool CreateQuestionTable(Hashtable map)
- {
- string strSql = @"IF object_id('" + map["TableName"].ToString() + "') IS NULL Create Table " + map["TableName"].ToString() + "(QuestionId varchar(20) ," +
- "ChapterId varchar(20) not null," +
- "QuestionTypeId varchar(20) not null," +
- "Degree int not null," +
- "Fraction float not null," +
- "QuestionContent text not null," +
- "Answer1 text," +
- "Answer2 text," +
- "Answer3 text," +
- "Answer4 text," +
- "CorrectAnswer text," +
- "IsValid varchar(10)," +
- "AddUser varchar(20)," +
- "Timestamp varchar(20)," +
- "Remark text," +
- "Other1 varchar(50)," +
- "Other2 varchar(50) constraint PK_" + map["TableName"].ToString() + " primary key (QuestionId))";
- int rows = DbHelperSQL.ExecuteSql(strSql.ToString());
- return true;
- }
- /// <summary>
- /// 添加一条题库信息
- /// </summary>
- public override bool InsertOneQuestion(Hashtable map)
- {
- StringBuilder strSql = new StringBuilder();
- strSql.Append("insert into" + map["TableName"].ToString ());
- strSql.Append("QuestionID,ChapterID,QuestionTypeId,Degree,Fraction,QuestionContent,Answer1,Answer2,Answer3,Answer4,CorrectAnswer,IsValid,AddUser,Remark,other1,other2)");
- strSql.Append(" values (");
- strSql.Append("@QuestionID,@ChapterID,@QuestionTypeId,@Degree,@Fraction,@QuestionContent,@Answer1,@Answer2,@Answer3,@Answer4,@Answer5,@Answer6,@Answer7,@CorrectAnswer,@IsValid,@AddUser,@Remark,@other1,@other2)");
- SqlParameter[] parameters = {
- new SqlParameter("@QuestionID",map["QuestionID"].ToString () ),
- new SqlParameter("@ChapterID",map["ChapterID"].ToString () ),
- new SqlParameter("@QuestionTypeId",map["QuestionTypeId"].ToString () ),
- new SqlParameter("@Degree",Convert.ToInt32 ( map["Degree"]) ),
- new SqlParameter("@Fraction",Convert.ToDouble ( map["Fraction"] )),
- new SqlParameter("@QuestionContent", map["QuestionContent"].ToString () ),
- new SqlParameter("@Answer1",map["Answer1"].ToString ()),
- new SqlParameter("@Answer2", map["Answer2"] .ToString ()),
- new SqlParameter("@Answer3",map["Answer3"].ToString ()),
- new SqlParameter("@Answer4",map["Answer4"].ToString ()),
- new SqlParameter("@CorrectAnswer",map["CorrectAnswer"].ToString () ),
- new SqlParameter("@IsValid", map["IsValid"].ToString () ),
- new SqlParameter("@AddUser", map["AddUser"].ToString ()),
- new SqlParameter("@Remark", map["Remark"].ToString () ),
- new SqlParameter("@other1", map["other1"] .ToString ()),
- new SqlParameter("@other2", map["other2"] .ToString ())};
- int rows = DbHelperSQL.ExecuteSql(strSql.ToString(), parameters);
- if (rows > 0)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- }</span>
总结:虽然题型不同,但是对题型的操作是一样的,这样我们就可以抽象出来一个
父类,然后利用反射根据选择的不同的题型,实例化不同的题型类。这样就将题型的变
化封装一起,当添加新题型的时候只需要导入一个DLL文件即可!