CSDN博客

img ecai

MFC和设计模式

发表于2004/6/26 21:17:00  2717人阅读

  MFC不是唯一一个使用了设计模式的程序库,也不可能是唯一的一个。可以肯定的说,所有好的框架必然是充满了好的设计模式。本文的目的在于提醒大家学习框架时,运用设计模式的理论和思想去理解其中众多的类之间的联系,从整体的角度去学习部分,显然比从部分去理解整体有更好的效果。本文的后面会给出MFC中的一些设计模式。

  但是,不得不悲哀的看到,MFC中的核心类CWnd(不知道的先拖下去打)违反了框架设计的一个基本准则:最小化。可以说,CWnd就是一个“根部肥大”的准则的好例子。不知道有多少人真正理解了CWnd中数以百计的成员函数?某种意义上,MFC普遍采用继承的方式实现,而很少采用组合类或者对象的方式,也是在一定意义上和软件设计模式相违背的。OO的三大特性中的继承,似乎误导我们尽可能的使用继承方式搭建框架,可是在设计模式中,可以看到组合是更加重要的方法。呜呼,本人也曾经是继承思想的受害者之一。

  不过,我必须承认,继承是比组合更加容易理解的方式,至少对于我如此。如果从完美的软件设计模式的角度,是否应该把CWnd拆分成更多的小接口?这样,我们的View,Dialog,button等等可以得到更加清晰的接口。但是这样的代价同样会增加框架的理解难度。从一个入门者的角度,我们不可能要求他先学习《设计模式》,然后去学习MFC。我的建议是,在学习MFC一段时间(半年?100个例子?理解MFC的20个类?)后,应该结合设计模式去学习。或许这也是学习框架的一个良好途径。

  不得不提醒诸位,请注意对于模式设计的过分使用的后果。netwind (往事如风)的文章(模式设计与形式主义)http://www.sawin.com.cn/doc/SD/Pattern/pattern.htm是一个非常好的例子。对于本人的经历,在刚开始接触设计模式思想的时候,简直有醍醐灌顶的感觉,啊,上帝,我以前的程序为何如此之烂?!现在,我要承认,设计模式好,但是使用不易,尤其对于我这个懒惰的Programmer,“原理要深,应用要快”是我的目标。这一点从我的“金山词霸的词库读取程序”中可以感受,一个运行了一个多小时的程序,我也会懒得再优化。:)

  小注:当然,众多晦涩难以理解的宏也为MFC的框架理解增添了不少“光彩”。一定程度上,我同意bigwhiteshark同志在http://dev.csdn.net/article/20/20831.shtm (对VC的批判,我要打击大家学VC的积极性了…… )文中的观点:从微软的策略看VC的前途!微软的策略是先用.net提供一个新的环境,然后逐步修改其OS,最终完全抛弃NT内核,其最终目的是抢占被UNIX和LINUX占据的高端市场份额(这是Borland李维说的,我觉得有道理)。现在推出的.net框架还支持原来的技术(如COM+),VC.net中也还有MFC7,但这只是一个过渡时期的产品,就象Windows 3.1被Windows 95取代一样,最终是要被抛弃的。

  最后的建议:限于本人的理论水平和时间精力,建议大家把自己对MFC中设计模式的理解也综合起来,相信这个是非常有意义的工作。我会继续进行这个工作的。

欢迎在我的blog:caijingwei.blogcn.com 上发表评论。

 

Factory

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。

框架创建它的View的过程。CFameWnd就是一个Creator,通过调用CFrameWnd::CreateView()创建不同的ConcreteProduct。

说明:其实CreateView()和动态创建对象的技术密切相关。这是MFC中一个比较有趣的设计,和C++的RTTI(运行时类型信息)不同。大家可以去研究RUNTIME_CLASS, DECLARE_DYNAMIC, DECLARE_DYNCREATE这几个宏。

 

Builder:

将一个复杂对象的构建和它的表示分离,使得同样的创建过程可以创建不同的表示。

在int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)中,创建框架窗口的过程:

m_wndDlgBar.Create()

m_wndReBar.Create()

m_wndStatusBar.Create()

是否可以理解为一个简化了的Builder模式?Director和Builder都是CMainFrame。

Adapter

将一个类的接口转换成客户希望的另外一个接口。

STL中的适配器:stack,queue,priority_queue。可以看作简化的Adapter模式,它改变了基类的接口,但是并没有组合其它对象。

说明:STL并不是MFC的一部分,是C++标准库的一部分,之所以放在本文中,可以认为是作者的偷懒。:)

Composite:    

所有的窗口类都从CWnd派生,而派生的窗口类又可以包含其它从CWnd派生的类,窗口间的父子关系构成了窗口的树形结构。这种机制就是设计模式中典型的结构型模式COMPOSITE(组合),即某个对象拥有一系列类似的对象,而这一系列对象中的每一个又拥有一系列的对象,如此递归下去,管理起来很方便。这是Windows消息处理的基本模型。

 

Proxy

为其它对象提供一种代理以控制这个对象的访问。智能指针(smart pointer),比如_com_ptr_t

 

Template:

相信学习MFC的同志有一个普遍的感觉:不知道使用哪个消息映射函数,即不知道哪里写代码。比如CDocument的OnNewDocument(),OnOpenDocument(),OnSaveDocument(),OnCloseDocument()。又比如打印的流程相关函数:PreparePrinting(),OnBeginPrinting(),OnPrepareDC(),OnPrint(),OnEndPrinting()。实际上这就是运用了Template模式:定义一个操作中的算法框架,而将一些步骤延迟到子类中。目的是使得子类不需要改变一个算法的结构即可重定义算法的某些特定步骤。很重要的一点是:基类必须指明哪些是钩子操作(可以选择被重定义),哪些是抽象操作(必须被重定义)。

Iterator:

STL中的Iterator,从名字和运作方式都很好的吻合了Iterator模式。如果要更加细分,STL中的Iterator属于外部迭代器,即由客户来控制迭代。

C#和VB中的foreach()语句。foreach()语句中操作的对象集合必须实现一个内部迭代器。

 

MVC

MVC模式是一个用于将用户界面逻辑与业务逻辑分离开来的基础设计模式,它将数据处理、界面以及用户的行为控制分为:Model-View-Controller。 

Model:负责当前应用的数据获取与变更及相关的业务逻辑 

View:负责显示信息 

Controller:负责收集转化用户的输入 

View和Controller都依赖于Model,但是Model既不依赖于View,也不依赖于Controller,这是分离的主要优点之一,这样Model可以单独的建立和测试以便于代码复用,View和Controller只需要Model提供数据,它们不会知道、也不会关心数据是存储在SQL Server还是Oracle数据库中或者别的什么地方。 。

MFC中的Doc-View结构可以看作是这种模式的一个简化,Document类相当于Model,似乎没有明确出现Controller,Controller的功能可以在Document类中实现。

0 0

相关博文

我的热门文章

img
取 消
img