问题:
在面向对象系统设计中经常可以遇到以下的两类问题:
问题1
为了提高内聚(Cohesion) 和松耦合(Coupling),需要我们抽象出一些类的公共接口以形成抽象基类或者接口。这样我们可以通过声明一个基类的指针指向子类对象进而达到多态的目的,但是这样很容易出现一个问题:n多的子类继承自抽象基类,我们不得不在每次要用到子类的地方就编写new xxx();这样就有两个问题产生:
- 必须要有实际子类的名称(命名困难,可读性和可记忆性都不友好)
- 程序的扩展性和维护变得困难
问题2
还有一种情况就是在父类中并不知道具体要实例化哪一个具体的子类。意思是:假如类B是一个抽象父类,A是一个类,现在我们在类 A 中要使用到类 B,但是在 A 中并不知道具体要实例化哪一个 B 的子类,但是在类 A 的子类 D 中是可以知道的,在 A 中我们没有办法直接使用类似于 new xxx()的语句,因为根本就不知道xxx是什么。
以上两个问题也就引出了 Factory 模式的两个最重要的功能:
- 定义创建对象的接口,封装了对象的创建;
- 使得具体化类的工作延迟到了子类中。
模式选择:
- 在第一个问题中,我们经常就是声明一个创建对象的接口,并封装了对象的创建过程。Factory 这里类似于一个真正意义上的工厂(生产对象)。
- 在第二个问题中,我们需要提供一个对象创建对象的接口,并在子类中提供其具体实现(因为只有在子类中可以决定到底实例化哪一个类)。
Factory 的结构示意图1
图 1 所以的 Factory 模式经常在系统开发中用到,但是这并不是 Factory 模式的最大威力所在(因为这可以通过其他方式解决这个问题)。Factory 模式不单是提供了创建对象的接口,其最重要的是延迟了子类的实例化(第二个问题),以下是这种情况的一个Factory 的结构示意图:
Factory 模式结构示意图 2
图 2 中关键中 Factory 模式的应用并不是只是为了封装对象的创建,而是要把对象的创建放到子类中实现,Factory 中只是提供了对象创建的接口,其实现将放在 Factory 的子类ConcreteFactory 中进行。这是图 2 和图 1 的区别所在。
实现
Product.h
#ifndef PRODUCT_H
#define PRODUCT_H
class Product
{
public:
virtual ~Product() = 0;
protected:
Product();
};
class ConcreteProduct:public Product
{
public:
~ConcreteProduct();
ConcreteProduct();
};
#endif // PRODUCT_H
Product.cpp
#include "product.h"
#include <iostream>
using namespace std;
Product::Product()
{
cout<<"CreateProduct"<<endl;
}
Product::~Product()
{
cout<<"DestoryProduct"<<endl;
}
ConcreteProduct::ConcreteProduct()
{
cout<<"ConcreteProduct...."<<endl;
}
ConcreteProduct::~ConcreteProduct()
{
cout<<"~ConcreteProduct...."<<endl;
}
factory.h
#ifndef FACTORY_H
#define FACTORY_H
class Product;
class Factory
{
protected:
Factory();
public:
virtual ~Factory() = 0;
virtual Product *CreateProduct() = 0;
};
class ConcreteFactory:public Factory
{
public:
~ConcreteFactory();
ConcreteFactory();
Product *CreateProduct();
};
#endif // FACTORY_H
factory.cpp
#include "factory.h"
#include "product.h"
#include <iostream>
using namespace std;
Factory::Factory()
{
cout<<"CreatedFactory..."<<endl;
}
Factory::~Factory()
{
cout<<"DestoryFactory..."<<endl;
}
ConcreteFactory::ConcreteFactory()
{
cout<<"ConcreteFactory..."<<endl;
}
ConcreteFactory::~ConcreteFactory()
{
cout<<"~ConcreteFactory..."<<endl;
}
Product *ConcreteFactory::CreateProduct()
{
return new ConcreteProduct();
}
main.cpp
#include <iostream>
#include "product.h"
#include "factory.h"
using namespace std;
void test()
{
Factory *fac = new ConcreteFactory();
Product *p = fac->CreateProduct();
delete fac;
delete p;
}
int main()
{
test();
return 0;
}