工厂模式
工厂模式一般分为三种:
- 简单工厂(Simple Factory)模式
- 工厂方法(Factory Method)模式
- 抽象工厂(Abstract Factory)模式
其中简单工厂与工厂方法在GoF中统称为工厂模式。由于所有创建型模式都的基本要求就是为对象的创建提供接口,封装对象的生成。所以简单工厂不专门作为一种创建型模式。但是简单工厂作为创建型模式的基本要求,虽然简单,也值得我们学习一番。
简单工厂(Simple Factory)模式
上面提到,简单工厂提供了创建型模式的基本功能,完成对对象创建的封装。其使用场景主要在当Product的种类太多导致类型名混乱时,使用对Factory传入参数的不同来区分不同种类的Product。注意: 以上所说的种类是指所有Product类均派生自同一基类,否则无法用参数将其区别开来。(参数就是它们属于同一基类的体现)
举个栗子:某车厂现生产多种品牌的车BWM 和 NIO等. 我们将其基本的功能属性抽象出父类Car,通过一个函数CreateCar的传入参数不同,确认生成的是那个子类的具体实例,返回基类指针. 这样我们就可以将对象的生成参数化,控制相同基类的子类对象的生成.
#include <iostream>
#ifndef _DESIGN_PATTERN_SIMPLE_FACTORY_CAR_HPP_
#define _DESIGN_PATTERN_SIMPLE_FACTORY_CAR_HPP_
namespace design_pattern
{
class Car
{
public:
virtual void name() = 0;
};
class BMW : public Car
{
public:
void name()
{
std::cout << "my name is BMW" << std::endl;
}
};
class NIO : public Car
{
public:
void name()
{
std::cout << "my name is NIO" << std::endl;
}
};
}
#endif //_DESIGN_PATTERN_SIMPLE_FACTORY_CAR_HPP_
//factory_car.hpp
#include "car.hpp"
#include <string>
#ifndef _DESIGN_PATTERN_SIMPLE_FACTORY_FACTORYCAR_HPP_
#define _DESIGN_PATTERN_SIMPLE_FACTORY_FACTORYCAR_HPP_
namespace design_pattern
{
class FactoryCar
{
public:
Car * CreateCar(std::string const &name)
{
if (name == std::string("BMW"))
return new BMW;
if (name == std::string("NIO"))
return new NIO;
return NULL;
}
};
}
#endif //_DESIGN_PATTERN_SIMPLE_FACTORY_FACTORYCAR_HPP_
//simple_factory_main.cpp
#include "car.hpp"
#include "factory_car.hpp"
using namespace design_pattern;
int main()
{
FactoryCar fac;
Car *pbmw = fac.CreateCar("BMW");
Car *pnio = fac.CreateCar("NIO");
pbmw->name();
pnio->name();
return 0;
}
显然,BMW与NIO都是由Car派生而来,在CreateCar函数中,由于其都对string name参数感兴趣才在创建时区分出了BMW与NIO。这就造成,当类进行扩展时,就要去修改CreateCar函数。也就是,若共工厂产品出现变化,NIO停产或者加入新的类型的车,这时我们需要将之前的CreateCar方法修改,造成对原有代码的入侵.不符合开放封闭原则
工厂方法(Factory Method)模式
由于产品体系过于庞大,产品体系出现分层现象。我们之前的简单工厂只能在同一层内区别产品的不同。当产品出现产品树时,我们的工厂模式也进一步以树形进行分层抽象。完成在叶子节点的创建,在中间节点的使用的功能。工厂方法模式也就此形成。
注意: 虽然工厂方法模式完成了产品的分层抽象及创建,但其依然局限于同类产品,所有产品必须拥有一个共同的基类。
假设,在FactoryCar中,我们并不知道它们可以通过name区分开来,因为这个类太过笼统。但我们知道在FactoryCar的子类中,随着工厂的逐步细化,在其子类FactoryBMW与FactoryNIO中我们就可以知道其创建的具体对象。
//car.hpp 与simple_factory中一致
//factory_car_series.hpp
#include "car.hpp"
#ifndef _DESIGN_PATTERN_FACTORY_METHOD_FACTORY_CAR_SERIES_HPP_
#define _DESIGN_PATTERN_FACTORY_METHOD_FACTORY_CAR_SERIES_HPP_
namespace design_pattern
{
class FactoryCarBase
{
public:
virtual Car * CreateCar() = 0;
};
class FactoryBMW : public FactoryCarBase
{
public:
Car * CreateCar()
{
return new BMW;
}
};
class FactoryNIO : public FactoryCarBase
{
public:
Car * CreateCar()
{
return new NIO;
}
};
}
#endif //_DESIGN_PATTERN_FACTORY_METHOD_FACTORY_CAR_SERIES_HPP_
//factory_method_main.cpp
#include "car.hpp"
#include "factory_car_series.hpp"
using namespace design_pattern;
int main()
{
FactoryBMW fbmw;
FactoryCarBase *pfac_base = &fbmw;
Car *bmw = pfac_base->CreateCar();
bmw->name();
FactoryNIO fnio;
pfac_base = &fnio;
Car *nio = pfac_base->CreateCar();
nio->name();
return 0;
}
显然,在父类FactoryCarBase中,我们并不知道创建那种Car,只有在其子类中我们才知道具体创建的种类。
当然,如果我们嫌FactoryCarBase通过继承方式太过浪费,那也可以采用之前的参数化工厂方法实现。
语法tips
- 相同namesapce中,无需再声明using即可使用。
- 编译器为一个类默认提供缺省成员函数均为public. example: class Test
- Test()
//constructor - ~Test()
//destructor - Test(Test const&)
//copy constructor - Test const& operator=(Test const&)
//assignment operator reload - Test* operator&()
//address-of operator reload - Test const* operator()const
//const address-of operator reload
- Test()