在面向对象系统设计中经常遇到以下的两类问题:
- 我们经常会抽象出一些类的公共接口以形成抽象基类或者接口。这样我们可以通过声明一个指向基类的指针来指向实际的子类对象,达到多态的目的。所以就不得不在要用到子类的地方new 一个子类对象,这样实体类的使用者必须知道实际的子类名称才能定义子类,如此一来会使程序的扩展性和维护变得越来越困难。
- 还有一种情况就是在父类中并不知道要实例化哪一个具体的子类。只能在父类中写方法调用,具体调用哪一个类的方法交给子类实现。
以上两个问题也就引出了 Factory 模式的两个最重要的功能:
- 1)定义创建对象的接口,封装了对象的创建。
- 2)使得具体化类的工作延迟到了子类中。
举例:
代码:
//product.h
#ifndef _PRODUCT_H_
#define _PRODUCT_H_
//定义一个产品基类
class Product
{
public:
virtual ~Product() = 0;
protected:
Product();
private:
};
//定义一个具体的产品类,派生自基类
class ConcreteProduct:public Product
{
public:
~ConcreteProduct();
ConcreteProduct();
protected:
private:
};
#endif // __PRODUCT_H_
//product.cpp
#include "Product.h"
#include <iostream>
using namespace std;
//产品基类构造函数
Product::Product()
{
cout<<"Product..."<<endl;
}
//产品基类析构函数
Product::~Product()
{
cout<<"~Product..."<<endl;
}
//特定产品的构造函数
ConcreteProduct::ConcreteProduct()
{
cout<<"ConcreteProduct..."<<endl;
}
//特定产品的析构函数
ConcreteProduct::~ConcreteProduct()
{
cout<<"~ConcretePruduct..."<<endl;
}
//factory.h
#ifndef _FACTORY_H_
#define _FACTORY_H_
class Product;
//工厂基类
class Factory
{
public:
virtual ~Factory() = 0;
protected:
Factory();
private:
};
//具体工厂类
class ConcreteFactory:public Factory
{
public:
~ConcreteFactory();
ConcreteFactory();
//创建一个指定产品的对象,具体产品类型由内部函数确定,产品类型对外是无感知的,返回指定产品的基类,实现多态
Product* CreateProduct();
protected:
private:
};
#endif // _FACTORY_H_
//factory.cpp
#include "Factory.h"
#include "Product.h"
#include <iostream>
using namespace std;
//工厂基类的构造函数
Factory::Factory()
{
cout<<"Factory..."<<endl;
}
//工厂基类的析构函数
Factory::~Factory()
{
cout<<"~Factory..."<<endl;
}
//特定工厂派生类的构造函数
ConcreteFactory::ConcreteFactory()
{
cout<<"ConcreteFactory..."<<endl;
}
//特定工厂派生类的析构函数
ConcreteFactory::~ConcreteFactory()
{
cout<<"~ConcreteFactory..."<<endl;
}
//创建一个指定产品的对象,具体产品类型由内部函数确定,对外是无感知的,返回指定产品的基类,实现多态
Product* ConcreteFactory::CreateProduct()
{
return new ConcreteProduct();
}
//main.cpp
#include "Factory.h"
#include "Product.h"
#include <iostream>
using namespace std;
int main(void)
{
ConcreteFactory *fac_ptr = NULL;
Product *pct_ptr = NULL;
/* 新建一个工厂对象,通过该工厂对象产生一个特定产品对象,具体的产品类型和细节对外层是透明的,
外层只需要通过产品基类定义的接口,访问产品功能即可 */
fac_ptr = new ConcreteFactory();
pct_ptr = fac_ptr->CreateProduct();
delete pct_ptr;
delete fac_ptr;
return 0;
}
运行结果:
总结:
可以看出,对与某一个具体的工厂ConcreteFactory类,其所生产的产品是ConcreteProduct类,通过工厂类的CreateProduct接口,实现内部对ConcreteProduct对象的封装和屏蔽;
main.c文件中只需要关注Product类(基类),不关注具体某个ConcreteProduct,采用多态特性,调用ConcreteProduct的接口。如此实现,在ConcreteProduct类内部做任何修改,都不影响main.c的代码逻辑。