工厂模式背景
日常生活中的工厂,通常是指拥有机器、设备构成的生产线,用以批量制造产生货物。软件设计中,也可以使用类似的方法,使用”工厂”批量生产”货物”。在飞车游戏中,若玩家飞车撞毁时,需要申请一辆新的飞车继续用,如此不断生产–销毁–再生产同类产品,与此同时,玩家在申请新的飞车时,也可以根据喜好选择不同类型,如“X7”、”Q5”等等,在选择型号即可, 这这里选择型号申请飞车的过程与生活中的工厂行为极为类似,可以试着模拟日常工厂行为进行类的实现。针对这种实际情况,软件工程提出了工厂模式,为创建对象提供了方法。
工厂模式根据实现层次不同,分为简单工厂模式(Simple Factory) 和工厂方法模式(Factory Method)。
简单工厂模式(Simple Factory)
简单工厂模式使用一个Factory类负责所有产品的创建,实现使用端和生产端分离,使用者不必关心产品的具体创建过程,只需要调用简单工厂类的Create方法获得想要的产品即可。
- 简单工厂模式UML图
- 简单工厂模式代码示例
class Car
{
public:
Car(){};
virtual ~Car(){};
public:
virtual void Drive() = 0;
};
class ConcreteCarA: public Car
{
public:
ConcreteCarA(){}
~ContreteCarA(){}
public:
virtual void Drive(){
//car A drive
}
};
class ConcreteCarB: public Car
{
public:
ConcreteCarB(){}
~ContreteCarB(){}
public:
virtual void Drive(){
//car A drive
}
};
//simple factory
class CarFactory
{
public:
CarFactory(){}
~CarFactory(){}
private:
Car *m_pCarInstance = NULL;
public:
virtual Car* CreateCar(CarType type)
{
if(type == Car_A)
m_pCarInstance = ConcreteCarA();
else if(type == Car_B)
m_pCarInstance ConcreteCarB();
return m_pCarInstance;
}
};
//客户端使用
Factory* m_pFactory = new CarFactory(); //建造工厂
Car* m_pCarA = m_pFactory->CreateCar(Car_A); //生产A
Car* m_pCarB = m_pFactory->CreateCar(Car_B); //生产B
但是,简单工厂模式违背了严格意义上的“开放封闭原则”,造成如果有一款新的产品增加就必须修改Factory类的源代码,将新产品加入简单工厂的创建逻辑,提供给使用者调用。
工厂方法模式(Factory Method)
工厂方法模式定义一个创建产品对象的工厂接口IFactory,将实际创建工作推迟到具体实现的子类当中,核心工厂类不再负责产品的创建,成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
工厂方法法模式是在简单工厂模式的基础上进一步抽象产生,使用了抽象工厂角色和面向对象的多态性,所有具体的工厂子类都必须实现这个接口。当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及生产该具体对象的对象工厂,原有工厂类不需要进行任何修改,不影响是使用者。该模式不仅保持了简单工厂模式的优点,而且克服了简单工厂模式违背“开放封闭原则”的缺点。
- 工厂方法模式UML图
- 工厂方法模式代码示例
class CarFactory
{
public:
CarFactory(){}
virtual ~CarFactory(){}
public:
virtual Car* CreateCar() = 0;
};
class ConcreteCarFactoryA : public CarFactory
{
public:
ConcreteCarFactoryA(){}
~ConcreteCarFactoryA(){}
private:
Car* m_pCarInstance;
public:
Car* CreateCar()
{
if(m_pCarInstance == NULL)
m_pCarInstance = new ConcreteCarA();
return m_pCarInstance;
}
};
class ConcreteCarFactoryB : public CarFactory
{
public:
ConcreteCarFactoryB(){}
~ConcreteCarFactoryB(){}
private:
Car* m_pCarInstance;
public:
Car* CreateCar()
{
if(m_pCarInstance == NULL)
m_pCarInstance = new ConcreteCarB();
return m_pCarInstance;
}
};
//客户端使用
//create FactoryA to generate Car A
Factory* m_pFactoryA = new ConcreteCarFactoryA(); //建造具体工厂A
Car* m_pCarA = m_pFactoryA->CreateCar(); //生产A
//create FactoryB to generate Car B
Factory* m_pFactoryB = new ConcreteCarFactoryB(); //建造具体工厂B
Car* m_pCarB =m_pFactoryA->CreateCar(); //生产B
工厂方法模式的不足之处在于: 使用者根据需要决定实例化哪一个具体的工厂,相当于把简单工厂模式的内部判断逻辑转移到了客户端代码。此外,该模式需要增加额外的代码,引起代码工作量的增加。