VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 1764|回复: 4

[原创] 辅助编程中的那些设计模式思想01-简单工厂

[复制链接]
05_avatar_middle
online_vip 发表于 2015-3-2 08:10:40 | 显示全部楼层 |阅读模式
01-简单工厂模式

很多人告诉我,你只要实现功能就可以了,不要去管他用什么方式,哪管用最简单的if - else 呢!

我也曾经这么走过来过,我也一直在努力用更好的方式去解决,也曾经走过弯路,用复杂的方案去解决本该简单的问题.

但是真的只要实现了就可以了么?

也许是吧..........

但是我更享受解决或者思考问题过程....

所以,有了这个系列的文章,并不仅仅为了什么,而是记录下,这些年走过的路而已...

所以你看了之后觉得是乱写一气也好,还是觉得看起来很牛逼也好,对于我来说真的不重要....

在我最开始写程序的那会,什么也不懂,也没有基础,遇到一个简单的问题都要卡上半天,第一次遇到一个印象很深刻的事情是这样的

话说,我要写配置,比如说 坐标 打怪范围之类的,还有要用什么技能 等等

我就写了2个函数

第一个函数 是控件读取值后保存到ini配置文件里去
第二个函数 是从ini读取出来,设置到控件里去

一开始我觉得没啥,很正常么,但是我写着写着就发现不对劲了,因为我每添加一个控件,

我首先要到,第一个函数里去添加代码 然后到第二个函数里去添加代码 , 当我添加到快20个控件的时候,我彻底放弃了.

当时我在想能不能用一种更方便的方式去解决这个问题?

代码的行为是一样的 都是读取 和 设置 控件

那么只要我把控件记录下来,就可以不用在添加如何去读取和设置了,

想到就干,当时问了SYC 如何通过指针去访问控件的方法后,就开始写代码了

我是这么写的,大家可以看看片段

  1. void CCtrlCon::_Show(map<CString,_Con>::iterator it)
  2. {
  3.         switch(it->second.Ctrltype)
  4.         {
  5.         case CON_CHECK:
  6.                 {
  7.                         if (it->second.value==__T("0"))
  8.                                 ((CButton*)(CWnd::FromHandle(it->second.CtrlHwnd)->GetDlgItem(it->second.Ctrlid)))->SetCheck(0);
  9.                         else
  10.                                 ((CButton*)(CWnd::FromHandle(it->second.CtrlHwnd)->GetDlgItem(it->second.Ctrlid)))->SetCheck(1);
  11.                         break;
  12.                 }
  13.         case CON_LISTBOX:
  14.                 {
  15.                         //清空控件
  16.                         ((CListBox*)(CWnd::FromHandle(it->second.CtrlHwnd)->GetDlgItem(it->second.Ctrlid)))->ResetContent();
  17.                         //循环读取结构中的值并赋值
  18.                         for (UINT i=0;i<it->second.stu.size();i++)
  19.                         {
  20.                                 ((CListBox*)(CWnd::FromHandle(it->second.CtrlHwnd)->GetDlgItem(it->second.Ctrlid)))->InsertString(i,it->second.stu.at(i).name);
  21.                         }
  22.                         //选择选中项
  23.                         ((CListBox*)(CWnd::FromHandle(it->second.CtrlHwnd)->GetDlgItem(it->second.Ctrlid)))->SelectString(0,it->second.Choose);
  24.                         break;
  25.                 }
  26.         case CON_COMBOX:
  27.                 {
  28.                         //清空控件
  29.                         ((CComboBox*)(CWnd::FromHandle(it->second.CtrlHwnd)->GetDlgItem(it->second.Ctrlid)))->ResetContent();
  30.                         //循环读取结构中的值并赋值
  31.                         for (UINT i=0;i<it->second.stu.size();i++)
  32.                         {
  33.                                 ((CComboBox*)(CWnd::FromHandle(it->second.CtrlHwnd)->GetDlgItem(it->second.Ctrlid)))->InsertString(i,it->second.stu.at(i).name);
  34.                         }
  35.                         //选择选中项
  36.                         ((CComboBox*)(CWnd::FromHandle(it->second.CtrlHwnd)->GetDlgItem(it->second.Ctrlid)))->SelectString(0,it->second.Choose);
  37.                         break;
  38.                 }
  39.         case CON_LISTCTL:
  40.                 {
  41.                         //清空控件
  42.                         ((CListCtrl*)(CWnd::FromHandle(it->second.CtrlHwnd)->GetDlgItem(it->second.Ctrlid)))->DeleteAllItems();
  43.                         for (UINT i=0;i<it->second.stu.size();i++)
  44.                         {
  45.                                 CString m;
  46.                                 //插入listctrl的行位置
  47.                                 int site = 0;
  48.                                 for (int j = 0;j<=32;j++)
  49.                                 {
  50.                                         if (((it->second.ConMode >> (j-1)) & 1))
  51.                                         {
  52.                                                 __char(l);
  53.                                                
  54.                                                 int k = 1;
  55.                                                 k = (k << (j-1));
  56.                                                 switch(k)
  57.                                                 {
  58.                                                 case CON_NAME:l = it->second.stu.at(i).name.GetBuffer();if(site == 0)CODE_INSERT it->second.stu.at(i).name.ReleaseBuffer();site++;break;
  59.                                                 case CON_SIZE:m = toc(it->second.stu.at(i).size);l = m.GetBuffer();if(site == 0) CODE_INSERT m.ReleaseBuffer();site++;break;
  60.                                                 case CON_NUM:m = toc(it->second.stu.at(i).num);l = m.GetBuffer();if(site == 0) CODE_INSERT m.ReleaseBuffer();site++;break;
  61.                                                 case CON_ID:m = toc(it->second.stu.at(i).id);l = m.GetBuffer();if(site == 0) CODE_INSERT m.ReleaseBuffer();site++;break;
  62.                                                 case CON_SYSYTEMID:m = toc(it->second.stu.at(i).systemid);l = m.GetBuffer();if(site == 0) CODE_INSERT m.ReleaseBuffer();site++;break;
  63.                                                 case CON_QUALITY:m = toc(it->second.stu.at(i).quality);l = m.GetBuffer();if(site == 0) CODE_INSERT m.ReleaseBuffer();site++;break;
  64.                                                 case CON_TIMER:m = toc(it->second.stu.at(i).timer);l = m.GetBuffer();if(site == 0) CODE_INSERT m.ReleaseBuffer();site++;break;
  65.                                                 case CON_X:m = toc(it->second.stu.at(i).x);l = m.GetBuffer();if(site == 0) CODE_INSERT m.ReleaseBuffer();site++;break;
  66.                                                 case CON_Y:m = toc(it->second.stu.at(i).y);l = m.GetBuffer();if(site == 0) CODE_INSERT m.ReleaseBuffer();site++;break;
  67.                                                 case CON_EXTENT:m = toc(it->second.stu.at(i).extent);l = m.GetBuffer();if(site == 0) CODE_INSERT m.ReleaseBuffer();site++;break;
  68.                                                 case CON_INTERVAL:m = toc(it->second.stu.at(i).interval);l = m.GetBuffer();if(site == 0) CODE_INSERT m.ReleaseBuffer();site++;break;
  69.                                                 case CON_TYPE:m = toc(it->second.stu.at(i).type);l = m.GetBuffer();if(site == 0) CODE_INSERT m.ReleaseBuffer();site++;break;
  70.                                                 case CON_TEXT1:l = it->second.stu.at(i).text1.GetBuffer();if(site == 0)CODE_INSERT it->second.stu.at(i).name.ReleaseBuffer();site++;break;
  71.                                                 case CON_TEXT2:l = it->second.stu.at(i).text2.GetBuffer();if(site == 0)CODE_INSERT it->second.stu.at(i).name.ReleaseBuffer();site++;break;
  72.                                                 case CON_TEXT3:l = it->second.stu.at(i).text3.GetBuffer();if(site == 0)CODE_INSERT it->second.stu.at(i).name.ReleaseBuffer();site++;break;
  73.                                                 }
  74.                                                
  75.                                         }
  76.                                 }
  77.                         }
  78.                         break;
  79.                 }
  80.         default:
  81.                 {
  82.                         SetDlgItemText(it->second.CtrlHwnd,it->second.Ctrlid,it->second.value);
  83.                         break;
  84.                 }
  85.         }
  86. }
复制代码


写出来以后感觉自己写的非常不错,直到某天看了本,叫大话设计模式的,发现原本程序可以这么写

在这个版本里,如果我要添加一个新的类型的控件,我依旧要到 很多函数里添加.看完了设计模式里的简单工厂后我重写了一个





  1. typedef class _CTRL_CHECK : public _CTRL_BTN
  2. {
  3. public:
  4.         _CTRL_CHECK(void);
  5. public:
  6.         BOOL m_bCheck;
  7. public:
  8.         VOID _CtrlUpdata();
  9.         VOID _CtrlShow();
  10.         VOID _SaveConfig(CString IniPath,CString IniName);
  11.         void _ReadConfig(CString IniPath,CString IniName);
  12. public:
  13.         BOOL GetCtrlCheck();
  14.         VOID SetCtrlCheck(BOOL IsCheck);
  15. public:

  16. }CTRL_CHECK;



  17. typedef class _CTRL_LIST : public MFC_CTRL
  18. {
  19. public:
  20.         CString m_Text;
  21.         INT m_nMaxCount;
  22.         INT m_nCurSel;
  23.         CString m_CurSelText;
  24. public:
  25.         INT GetCtrlCurSel();
  26.         INT GetCtrlMaxCount();
  27. }CTRL_LIST;



  28. typedef class _CTRL_EDIT : public _CTRL_TEXT
  29. {
  30. public:
  31.         VOID _CtrlUpdata();
  32.         VOID _CtrlShow();
  33.         VOID _SaveConfig(CString IniPath,CString IniName);
  34.         void _ReadConfig(CString IniPath,CString IniName);
  35. public:
  36.         CString GetCtrlText();
  37.         INT GetCtrlInt();
  38.         VOID SetCtrlText(CString Text);
  39.         VOID SetCtrlInt(INT Text);
  40. }CTRL_EDIT;
复制代码



我将每个控件定义成一个类,继承同一个接口,这样即使我在添加一个新的控件的话 我也只需要添加新的类即可



  1. void _CTRL_FACTORY::Register(CString CtrlName,HWND CtrlHwnd,int CtrlID,int CtrlType,int Group,bool IsSave,bool IsUpData,bool IsRead)
  2. {
  3.         EnterCriticalSection(&cs_);
  4.         //查找表里是否存在同样名字的
  5.         map<CString,m_ConStu>::iterator it = m_CtrlConData.find(CtrlName);

  6.         if (it == m_CtrlConData.end())
  7.         {
  8.                 //不存在增加
  9.                 m_ConStu ConStu;

  10.                 switch(CtrlType)
  11.                 {
  12.                 case NULL:                        ConStu.CTRL = new _CTRL_CONFIG;                break;
  13.                 case CON_CHECK:                ConStu.CTRL = new _CTRL_CHECK                ;break;
  14.                 case CON_EDIT:                ConStu.CTRL = new _CTRL_EDIT                ;break;
  15.                 case CON_COMBOX:        ConStu.CTRL = new _CTRL_COMBO                ;break;
  16.                 case CON_LISTBOX:        ConStu.CTRL = new _CTRL_LISTBOX                ;break;
  17.                 case CON_LISTCTRL:        ConStu.CTRL = new _CTRL_LISTCTRL        ;break;
  18.                 case CON_STATIC:        ConStu.CTRL = new _CTRL_STATIC                ;break;
  19.                 case CON_BTN:                ConStu.CTRL = new _CTRL_BUTTON                ;break;
  20.                 case CON_MENU:      ConStu.CTRL = new _CTRL_MENU        ;break;

  21.                 }
复制代码




然后 在添加到注册里.

这是第一次接触到设计模式,但对我来说触动非常大,原来发现程序还可以这样设计,从此之后我便一发不可收拾.

简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类







上一篇:采桑子(月夜)
下一篇:辅助编程中的那些设计模式思想02-迭代器模式
56_avatar_middle
在线会员 发表于 2015-3-2 10:25:17 | 显示全部楼层
顶一下楼主,感谢楼主的分享。。
72_avatar_middle
online_vip 发表于 2015-9-8 01:15:11 | 显示全部楼层
支持楼主,感谢无私分享.祝楼主技术日益精湛
80_avatar_middle
在线会员 发表于 2016-5-25 10:01:07 | 显示全部楼层

顶一下楼主,感谢楼主的分享。。
17_avatar_middle
在线会员 发表于 2017-1-21 23:20:55 | 显示全部楼层
这个挺有用.会写了也要学这个才得
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2019-6-26 06:43

Powered by Discuz! X3.4

© 2009-2019 cctry.com

快速回复 返回顶部 返回列表