现在的位置: 首页 > 综合 > 正文

论道——工厂模式与装饰模式的融合  论道——工厂模式与装饰模式的融合

2017年09月28日 ⁄ 综合 ⁄ 共 6323字 ⁄ 字号 评论关闭
 

[置顶] 论道——工厂模式与装饰模式的融合

分类: web 三层 393人阅读 评论(36) 收藏 举报

目录(?)[+]

        在做项目之前总绝得需求为王很对,但是到自己的代码中,总是感觉不得要领,一直到我们做考试系统,大家讨论需求的时候,需求的各种乱,各种不知道怎么平衡,各种讨论,再到一个个的确定,一个个得多方平衡,才明白,需求就是一切!

        今天给大家介绍一个特殊的需求,在做考试系统的过程中,我们的想要将题型的变化封装到dll里,设计模式里的装饰模式可以做到增加一个新的题型而不动代码,但是他有个弊端就是客户端要实例具体的题型类,我想将创建也 封装起来,就用简单工厂模式对装饰者做了个优化,现在给大家分享:


1,装饰模式第一版:

        


代码:


抽象页面

  1. <span style="font-size:18px">/// <summary>  
  2.     /// 装饰者——抽象的页面——组卷的抽象类  
  3.     /// </summary>  
  4.     public class AbstractPage  
  5.     {  
  6.        // public double Fraction;  
  7.         //展示页面  
  8.         public virtual void ShowPage()   
  9.         { }   
  10.     }</span>  



问题页面


  1. <span style="font-size:18px">/// <summary>  
  2.     /// 装饰者模式——题的抽象展示页面  
  3.     /// </summary>  
  4.     public class QuestionsPage:AbstractPage  
  5.     {  
  6.         //每个题里都有一个页面——可以看做未具体题型在这里的暂存位置,将各个题型的作为另一个题型的属性  
  7.         protected AbstractPage LittleQuestionsPage;  
  8.   
  9.         protected static double AllFraction;  
  10.   
  11.         public double GetAllFraction()  
  12.         {  
  13.             return AllFraction;  
  14.         }  
  15.   
  16.         //加入新的题型,做到题型的累加,将各个题型串联起来  
  17.         public void AddQuestionsPage(AbstractPage QuestionsPage)  
  18.         {  
  19.             this.LittleQuestionsPage = QuestionsPage;  
  20.         }  
  21.   
  22.         //抽象的显示,显示具体的题型内的题型页面  
  23.         public override void ShowPage()  
  24.         {  
  25.             if (LittleQuestionsPage!=null)  
  26.             {  
  27.                 LittleQuestionsPage.ShowPage();  
  28.             }  
  29.         }  
  30.   
  31.     }</span>  

其中一个具体的页面(选择题)


  1. <span style="font-size:18px">    /// <summary>  
  2.     /// 显示选择题——装饰者  
  3.     /// </summary>  
  4.     public class ChoiceQuestionPage : QuestionsPage  
  5.     {  
  6.   
  7.         /// <summary>  
  8.         /// 构造类  
  9.         /// </summary>  
  10.         public ChoiceQuestionPage()   
  11.         {  
  12.               
  13.   
  14.         }  
  15.         //抽象的显示,显示具体的题型内的题型页面  
  16.         /// <summary>  
  17.         /// 显示选择题  
  18.         /// </summary>  
  19.         public override void ShowPage()  
  20.         {  
  21.             //较为关键代码——先显示自己包含的装饰者的装饰  
  22.             base.ShowPage();  
  23.   
  24.   
  25.             ///页面显示选择题——略  
  26.   
  27.     }</span>  

 总结:

        整个的装饰模式相当于将每个纸片打孔,让他可以和具体的纸片用钩子连接起来,这样牵动最后一个纸片,就会带出所有的纸片,直到纸片上没有钩子!这个在生活中经常用到,比如我们的笔记本:


2,装饰模式第二版:




        这样就用简单工厂封装了装饰者模式客户端分拣的过程,将变化进一步封装,优化了结构,使得变化更加灵活!


代码:

工厂


  1. <span style="font-size:18px">using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.UI;  
  6. using System.Web.UI.WebControls;  
  7. using ExamSystemV3.Web;  
  8. using ExamSystemV3.Model;  
  9. using BLL;  
  10. using ExamSystemV3.Common;  
  11. using System.Globalization;  
  12. using System.Data;  
  13. using System.Collections;  
  14. using System.Web.SessionState;  
  15.   
  16. namespace ExamSystemV3.Web.web_class  
  17. {  
  18.     public class CreatQuestion  
  19.     {  
  20.         /// <summary>  
  21.         /// 显示dataset里试题的页面  
  22.         /// </summary>  
  23.         /// <param name="ds">存放试题的dataset 要求:ds.DataSetName+"_"+ dt.TableName + "_Record" 能拼出答题记录表例如:ds.DataSetName="T_tongjixue" dt.TableName="xvanzeti" 则拼接出的答题记录表为"T_tongjixue_xvanzeti_Record" </param>  
  24.         /// <param name="isExaminghtml">页面中能够盛放试题的div的id</param>  
  25.         /// <param name="_FlagChooseQuestion">是否是二次登陆</param>  
  26.         /// <param name="_ExamId">考试id</param>  
  27.         /// <param name="_StudentId">学号</param>  
  28.         /// <returns>返回携带所有问题的QuestionsPage</returns>  
  29.         public QuestionsPage StuCreateQuestion(DataSet ds)  
  30.         {  
  31.             int i,j;  
  32.             DataTable dt;  
  33.             ArrayList arrAllQuestion=new ArrayList();  
  34.             ArrayList arrQuestion=new ArrayList();  
  35.   
  36.             //创建所有的题型page类放到arrAllQuestion  
  37.             for (i = 0; i <= ds.Tables.Count - 1; i++)  
  38.             {  
  39.   
  40.                 dt=ds.Tables[i];  
  41.                 arrQuestion = DataTableToArrylist(dt);  
  42.                 strRecordTableName =ds.DataSetName+"_"+ dt.TableName + "_Record";  
  43.                 qsPageLittle = CreatePage(dt, isExaminghtml, _FlagChooseQuestion, BigQuestionNum, arrQuestion, strRecordTableName, _ExamId, _StudentId);  
  44.                 BigQuestionNum = BigQuestionNum + 1;  
  45.                 arrAllQuestion.Add( qsPageLittle );  
  46.                   
  47.                   
  48.             }  
  49.             //将所有具体的页面封装在一个页面中  
  50.             for (j = arrAllQuestion.Count-1; j >= 1; j--)  
  51.             {  
  52.                 qsPageLittle = (QuestionsPage)arrAllQuestion[j - 1];  
  53.                 ((QuestionsPage)arrAllQuestion[j]).AddQuestionsPage(qsPageLittle);  
  54.             }  
  55.         //返回封装好的最后一个页面  
  56.             qsPageall = (QuestionsPage)arrAllQuestion[arrAllQuestion.Count - 1];  
  57.             return qsPageall;  
  58.   
  59.           
  60.         }  
  61.           
  62.         //创建不同的页面  
  63.         private QuestionsPage CreatePage(DataTable dt, System.Web.UI.HtmlControls.HtmlGenericControl isExaminghtml, string _FlagChooseQuestion, int _BigQuestionNum, ArrayList _arrAllQuestion, string _strSingleSelectionRecordTableName, string _ExamId, string _StudentId)  
  64.         {  
  65.             QuestionsPage ChildQuestionPage;  
  66.             switch (dt.TableName)  
  67.             {  
  68.   
  69.                 //ChoiceQuestionPage  
  70.                 //选择题  
  71.                 case "xuanzeti":  
  72.                     ChildQuestionPage = new ChoiceQuestionPage(isExaminghtml, _FlagChooseQuestion, _BigQuestionNum, _arrAllQuestion, _strSingleSelectionRecordTableName, _ExamId, _StudentId);  
  73.                     break;  
  74.   
  75.                 //MultiSelectQestionPage  
  76.                 //多选题  
  77.                 case "duoxuanti":  
  78.                     ChildQuestionPage = new MultiSelectQestionPage(isExaminghtml, _FlagChooseQuestion, _BigQuestionNum, _arrAllQuestion, _strSingleSelectionRecordTableName, _ExamId, _StudentId);  
  79.                     break;  
  80.   
  81.                   
  82.                 // AnalysisQuestionPage  
  83.                 //案例分析题  
  84.                 case "anlifenxiti":  
  85.                     ChildQuestionPage = new AnalysisQuestionPage(isExaminghtml, _FlagChooseQuestion, _BigQuestionNum, _arrAllQuestion, _strSingleSelectionRecordTableName, _ExamId, _StudentId);  
  86.                     break;  
  87.   
  88.                //剩下的略  
  89.   
  90.                 default:  
  91.                     ChildQuestionPage=null;  
  92.                     break;  
  93.             }  
  94.   
  95.             return ChildQuestionPage;  
  96.   
  97.         }  
  98.   
  99. }</span>  


         大家研究不难发现,其实就是case语句的功劳!


3,装饰模式,简单工厂模式总结:


        我们写代码的时候,要充分考虑封装变化,将变化封装到模块中,增加模块内的内聚性,做到变化的改动尽量不重新生成,即使生成也是很小的改动,增加我们系统的灵活性和可靠性!要多思考,多总结!


注:为了照顾篇幅,本人已精简代码,只保留骨干部分,如有需要查看全部代码,请留言,共同交流!

抱歉!评论已关闭.