一、简介
Factory 模式是为了解决两类问题:
1、Factory封装对象的创建
第一种问题是为了提高内聚(Cohesion)和松耦合(Coupling),我们经常会抽象出一些类的公共接口以形成抽象基类或者接口。这样我们可以通过声明一个指向基类的指针来指向实际的子类实现,达到了多态的目的。这里很容易出现的问题是 n 多的Product的子类继承自抽象基类Product,不得不在每次要用到子类的地方就编写诸如 new ConcreteProduct的代码,带来的麻烦即是:(1)客户程序员必须知道实际子类的名称如ConcreteProduct1、ConcreteProduct2等,当系统复杂后,命名将是一个很不好处理的问题(2)程序的扩展性和维护变得越来越困难,必须保存每一个对象的指针。
为了解决上述问题,我们经常就是使用Factory模式声明一个创建对象的接口,并封装了对象的创建过程。Factory 这里类似于一个真正意义上的Factory工厂(生产对象)。如下图所示:
在工厂中即可使用:
Product *ConcreteFactory::CreateProduct(int number)
{
switch(number) {
case 1:
return new ConcreteProduct1();
break;
case 2:
return new ConcreteProduct2();
break;
case 3:
return new ConcreteProduct3();
break;
}
}
2、Factory具体化类延迟到子类
第二种问题是在父类Factory中并不知道具体要实例化哪一个具体的子类,比如Factory类中要使用类Product(抽象父类),但Factory中并不知道具体要实例化ConcreteProduct1还是ConcreteProduct3,但在Factory类的子类ConcreteFactory中是可以知道的,故Factory类将具体化类的工作延迟到了子类ConcreteFactory中,使用newConcreteProduct1或new ConcreteProduct3。
该设计与第一种的区别在于并不是只是为了封装类Product的子类对象的创建,而是要把对象的创建延迟到子类ConcreteFactory中实现,因为有时只有子类中可以决定到底实例化哪一个类。
Product *ConcreteFactory::CreateProduct() //创建操作
{
if (_flag == 1) {
return new ConcreteProduct1(); //子类中决定要实例化哪一个类
}
else if (_flag == 3){
return new ConcreteProduct3();
}
}
二、详解
1、代码实现
(仅实现第二种功能代码,完整代码已上传到csdn)
(1)代码product.h:
#ifndef _PRODUCT_H_
#define _PRODUCT_H_
class Product
{
public:
virtual ~Product() = 0;
protected:
Product();
private:
};
class ConcreteProduct1 : public Product
{
public:
~ConcreteProduct1();
ConcreteProduct1();
protected:
private:
};
class ConcreteProduct3 : public Product
{
public:
~ConcreteProduct3();
ConcreteProduct3();
protected:
private:
};
#endif
(2)代码product.cpp:
#include "product.h"
#include<iostream>
using namespace std;
Product::Product()
{
cout<<"Product constructor"<<endl;
}
Product::~Product()
{
cout<<"Product destructor"<<endl;
}
ConcreteProduct1::ConcreteProduct1()
{
cout<<"ConcreteProduct1 constructor"<<endl;
}
ConcreteProduct1::~ConcreteProduct1()
{
cout<<"ConcreteProduct1 destructor"<<endl;
}
ConcreteProduct3::ConcreteProduct3()
{
cout<<"ConcreteProduct3 constructor"<<endl;
}
ConcreteProduct3::~ConcreteProduct3()
{
cout<<"ConcreteProduct3 destructor"<<endl;
}
(3)代码factory.h:
#ifndef _FACTORY_H_
#define _FACTORY_H_
class Product;
class Factory
{
public:
virtual ~Factory() = 0;
virtual Product *CreateProduct() = 0;
void setFactoryMethod(int flag);
protected:
Factory();
int _flag;
private:
};
class ConcreteFactory : public Factory
{
public:
~ConcreteFactory();
ConcreteFactory();
virtual Product *CreateProduct();
protected:
private:
};
#endif
(4)代码factory.cpp:
#include "product.h"
#include "factory.h"
#include <iostream>
using namespace std;
Factory::Factory()
:_flag(0)
{
}
Factory::~Factory()
{
}
void Factory::setFactoryMethod(int flag)
{
_flag = flag;
}
ConcreteFactory::ConcreteFactory()
{
cout<<"---ConcreteFactory constructor"<<endl;
}
ConcreteFactory::~ConcreteFactory()
{
cout<<"---ConcreteFactory destructor"<<endl;
}
Product *ConcreteFactory::CreateProduct() //创建操作
{
if (_flag == 1) {
return new ConcreteProduct1(); //子类中决定要实例化哪一个类
}
else if (_flag == 3){
return new ConcreteProduct3();
}
}
(5)代码main.cpp:
#include "factory.h"
#include "product.h"
#include <iostream>
using namespace std;
int main()
{
Factory *fac = new ConcreteFactory();
//ConcreteFactory延时通过决定参数决定到底创建具体哪一个Product的子类
fac->setFactoryMethod(3);
Product *pro = fac->CreateProduct();
if (pro) {
delete pro;
pro = NULL;
}
if (fac) {
delete fac;
fac = NULL;
}
return 0;
}
(6)makefile文件:
CFLAGS = -g
DEFINED = #-D _VERSION
LIBS =
CC = g++
INCLUDES = -I./
OBJS= main.o factory.o product.o
TARGET= main
all:$(TARGET)
$(TARGET):$(OBJS)
$(CC) $(CFLAGS) -o $@ $(OBJS)
.SUFFIXES:.o .h
.SUFFIXES:.cpp .o
.cpp.o:
$(CC) $(DEFINED) -c $(CFLAGS) -o $@ $<
ok:
./$(TARGET)
clean:
rm -f $(OBJS) $(TARGET) core *.log
2、运行结果
(centos6.3系统中运行结果:)
三、总结
(1)Factory 模式在实际开发中应用非常广泛,面向对象的系统经常面临着对象创建问题:要创建的类实在是太多了,而 Factory 提供的创建对象的接口封装(第一个功能),以及其将类的实例化推迟到子类(第二个功能)都部分地解决了实际问题。
(2)在实现中通过参数化工厂方法fac->setFactoryMethod(3)决定是创建具体哪一个具体的Product的子类是非常有用的。
(3)Factory 模式带来的问题:如果为每一个具体的ConcreteProduct类的实例化提供一个函数体,那么我们可能不得不在系统中添加了一个方法来处理这个新建的 ConcreteProduct,这样 Factory 的接口永远就不肯能封闭(Close)。当然我们可以通过创建一个 Factory 的子类来通过多态实现这一点,但是这也是以新建一个类作为代价的。虽然Factory 模式对于对象的创建给予开发人员提供了很好的实现策略,但是Factory 模式仅仅局限于一类类(就是说 Product 是一类,有一个共同的基类),如果我们要为不同类的类提供一个对象创建的接口,那就要用 AbstractFactory 了。
(4)源码已经打包上传到csdn上可登录下载(http://download.csdn.net/detail/taiyang1987912/8401713)。