在之前的《设计模式:工厂模式》中记录了两种用于创建派生类对象的工厂模式,第一种模式直接使用基类的静态成员函数来创建派生类的对象,在该静态成员函数中直接调用了派生类的构造函数,第二种模式是使用基类工厂的静态成员函数,通过基类工厂中保存的各派生类工厂来创建派生类对象,派生类工厂是派生类的嵌套类,相当于为派生类量身定做的专属工厂,这些专属工厂的存在使得基类工厂不必了解创建派生类对象的细节。今天主要记录另外两种工厂模式:虚构造函数和抽象工厂。虚构造函数模式与前两种工厂模式不同,在前两种工厂模式中,基类是基类,派生类是派生类,在虚构造函数模式中,基类虽然还是基类,但是基类的行为却是派生类的行为,所以从作用效果上看,基类貌似就是派生类了,下面看一个简单的例子:
class Base { Base *p; protected: Base() { p = NULL; } public: Base(const string &str); ~Base(); virtual void func() { p->func(); } };
这是基类的定义,基类中有一个基类的指针:p ,这个指针最终将指向一个派生类对象,注意到在基类的成员函数func()中,通过p调用了派生类的func(),所以基类的行为就是派生类的行为,下面我们看一下Base(const string &str)的定义:
Base::Base(const string &str) { if(str=="A") p = new A(); if(str=="B") p = new B(); }
所以当我们调用上述构造函数来创建一个基类对象时,同时将基类的成员指针p指向了一个派生类对象,接下来这个基类对象的所有行为都是派生类的行为,所以基类对象看起来就像一个派生类对象,这就是所谓的“虚构造函数”。下面是完整的代码:
#include<iostream> #include<string> using namespace std; class Base { Base *p; protected: Base() { p = NULL; } public: Base(const string &str); ~Base(); virtual void func() { p->func(); } }; class A : public Base { A() {} A(const A&) {} friend class Base; public: void func() { cout<<"This is from A"<<endl; } }; class B : public Base { B() {} B(const B&) {} friend class Base; public: void func() { cout<<"This is from B"<<endl; } }; Base::Base(const string &str) { if(str=="A") p = new A(); if(str=="B") p = new B(); } Base::~Base() { delete p; } int main() { Base *s = new Base("A"); s->func(); delete s; return 0; }
需要注意的是Base中还有一个无参的默认构造函数,这个构造函数将在创建派生类对象的时候被调用,来初始化派生类对象中的基类子对象,即来初始化p,不过这个p对于我们而言是没用的,所以将之初始化为0,不过令p=0还有一个好处,因为在销毁基类对象的时候会调用基类的析构函数,在析构函数中有delete p,这将引发派生类的析构函数,之后派生类的析构函数又会调用基类子对象的析构函数,即会第二次调用基类的析构函数,唯一不同的是此p非彼p,如果此p不为0,可能引发未知的后果。
抽象工厂模式也很简单,其本意是有一大堆派生类工厂,这些派生类工厂根据自己的需要创建合适的对象,直接看代码或许更直观:
class BaseA {}; class A1 : public BaseA{}; class A2 : public BaseA{}; class BaseB {}; class B1 : public BaseB {}; class B2 : public BaseB {}; class Factory { public: virtual BaseA* createA() = 0; virtual BaseB* createB() = 0; }; class OneFactory : public Factory { BaseA* createA() { return new A1(); } BaseB* createB() { return new B1(); } }; class TwoFactory : public Factory { BaseA* createA() { return new A2(); } BaseB* createB() { return new B2(); } };
Factory提供公共的接口,OneFactory根据自己的需要重新定义createA和createB,生成A1和B1的对象,TwoFactory也是根据自己的需要重新定义createA和createB,来分别生成A2和B2的对象。使用方式如下:
int main() { Factory *p1 = new OneFactory(); p1->createA(); Factory *p2 = new TwoFactory(); p2->createA(); return 0; }