如果要选择一种最多人熟悉的Factory Method模式的具体应用,那么就应该是MFC的App/Doc架构了。Factory Method主要在类框架中使用,以解决以下问题:框架必须实例化类,但框架只知道不能被实例化的抽象类。嗯,这么说有点抽象,我们上图:
上面的图中,基类Application有一个成员函数NewDocument用于创建并打开新文档(你可以将这个函数想象为对File->New菜单的响应)。该函数完成以下工作:
1. 创建新文档
2. 将该文档加入App以便于管理(比如挂到打开文档链表中)
3. 打开该文档
NewDocument函数的这三个步骤对任意类型的文档都适用,因此是属于框架的。由于框架的设计者不可能预先知道框架的使用者会创建一个什么样的文档,因此必须将CreateDocument函数交由框架使用者来实现,但在框架中又不得不调用CreateDocument这个暂时还无法实现的函数以完成上述步骤1。面临同样问题的还有Document类的Open函数。解决办法是将Application类的CreateDocument函数和Document类的Open函数实现为虚函数,并由框架使用者实现之。下面是代码:
1 // FactoryMethod.cpp : Defines the entry point for the console application. 2 // 3 4 #include "stdafx.h" 5 #include6 7 using namespace std; 8 9 class App;10 class Doc;11 class DerivedApp;12 class DerivedDoc;13 14 class Doc15 {16 public:17 virtual void Open() = 0;18 };19 20 class DerivedDoc : public Doc21 {22 public:23 virtual void Open()24 {25 cout << "DerivedDoc opened." << endl;26 }27 };28 29 class App30 {31 public:32 virtual Doc* CreateDoc() = 0;33 void NewDoc()34 {35 Doc *doc = CreateDoc();36 cout << "Add new doc to the system." << endl;37 doc->Open();38 }39 };40 41 class DerivedApp : public App42 {43 public:44 virtual Doc* CreateDoc()45 {46 return new DerivedDoc;47 }48 };49 50 int _tmain(int argc, _TCHAR* argv[])51 {52 App *app = new DerivedApp;53 app->NewDoc();54 return 0;55 }
呃,为了偷懒,我将Application类缩写为App,Document类缩写为Doc。除此以外,这段代码基本上是和类图完全对应的。
顺便吐槽下,Abstract Factory模式和Builder模式在网上能搜索到的文章数量及质量完败后续所有模式。莫非虎头蛇尾雷声大雨点小决心巨人行动矮子的并不只是本人……