工厂(Factory)处理创建对象的细节,只负责创建对象。方便不同的对象需要时通过工厂来获取对象。
简单工厂其实不是一种设计模式,反而比较像是一种编程习惯。但是由于经常被使用,有些开发人员把这个编程习惯误认为是“工厂模式”。
简单工厂模式:实例化对象的时候不再使用 new Object()的形式,根据用户选择的产品类名或者某个标识来实例化具体的类。但是会业务扩展而使得简单工厂类数量庞大。
工厂方法模式:工厂方法模式是对简单工厂模式进一步的解耦,在工厂方法模式中是一类产品对应一个工厂类,而这些工厂类都继承于一个抽象工厂。这相当于是把原本会随着业务扩展而数量庞大的简单工厂类,分类成了一个个的具体产品工厂类,这样代码就不会都耦合在同一个类里。
工厂方法模式定义了一个创建对象的接口,但由子类决定要具体实现化的类是哪一个。工厂方法让类把实例化推迟到子类。
假设现在我们准备开一家披萨店,不同种类的披萨都有相同的一套制作流程:被准备、被烘烤、被切片、被装盒,但是不同的披萨有不同的口味和添加不同的配料比如cheese、veggie等。随着业务的扩展,来自不同地方的风味各异的披萨店准备来加盟,它们有不同的风味但是需要添加的配料还是相同。(后续扩展:实现一个原料工厂生产不同的原料:抽象工厂模式)
设计原则
依赖倒置原则:披萨店最开始的设计是一家披萨店直接生产各个具体的披萨类,这样导致披萨店(高层组件)过分依赖各个具体的披萨类(低层组件)。解决方法是抽象出一个Pizza类,让高层组件和低层组件都依赖于这个抽象类。
类图:
把变化和不变化的部分分离,把可能变化的具体披萨类的生产封装在一个工厂中。
由于Pizza对象是抽象的,orderPizza()并不知道哪些具体类参与进来了,换句话说,这就是解耦(decouple)。
加盟店有它的好处,可以从PizzaStore继承获得所有的功能。加盟店只需要继承PizzaStore,然后提供createPizza()方法实现自己的披萨风味即可。注意,超类的orderPizza()方法并不知道创建的披萨是哪一种,它只知道这个披萨可以被准备、被烘烤、被切片、被装盒。
缺点
当需要新增产品时,都必须要编写新的具体产品类,而且还要提供与之对应的具体工厂类,随着类的不断增加,在一定程度上增加了系统的复杂度,会有更多的类需要编译和加载,会给系统带来一些额外的开销。
实现如下:
pizzaStore.h:
#ifndef PIZZASTORE_H
#define PIZZASTORE_H
#include "pizza.h"
class PizzaStore {
public:
virtual Pizza* orderPizza(string type) = 0;
virtual Pizza* createPizza(string type) = 0;
};
#endif // PIZZASTORE_H
NYPizzaStore.h:
#ifndef NYPIZZASTORE_H
#define NYPIZZASTORE_H
#include "pizzaStore.h"
#include "NYStyleCheesePizza.h"
class NYPizzaStore : public PizzaStore {
public:
virtual Pizza* orderPizza(string type) override;
virtual Pizza* createPizza(string type) override;
};
Pizza* NYPizzaStore::createPizza(string type)
{
Pizza* pizza;
if(type == "cheese")
{
pizza = new NYStyleCheesePizza();
}
return pizza;
}
Pizza* NYPizzaStore::orderPizza(string type)
{
Pizza* pizza;
pizza = createPizza(type);
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box();
return pizza;
}
#endif // NYPIZZASTORE_H
ChicagoPizzaStore.h:
#ifndef CHICAGOPIZZASTORE_H
#define CHICAGOPIZZASTORE_H
#include "pizzaStore.h"
#include "ChicagoStyleVeggiePizza.h"
class ChicagoPizzaStore : public PizzaStore {
public:
virtual Pizza* orderPizza(string type) override;
virtual Pizza* createPizza(string type) override;
};
Pizza* ChicagoPizzaStore::createPizza(string type)
{
Pizza* pizza;
if(type == "veggie")
{
pizza = new ChicagoStyleVeggiePizza();
}
return pizza;
}
Pizza* ChicagoPizzaStore::orderPizza(string type)
{
Pizza* pizza;
pizza = createPizza(type);
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box();
return pizza;
}
#endif // CHICAGOPIZZASTORE_H
pizza.h:
#ifndef PIZZA_H
#define PIZZA_H
#include <iostream>
#include <string>
using namespace std;
class Pizza {
public:
void prepare();
void bake();
void cut();
void box();
void display();
protected:
string m_type;
};
void Pizza::prepare()
{
cout << "准备,";
}
void Pizza::bake()
{
cout << "烘烤,";
}
void Pizza::cut()
{
cout << "切片,";
}
void Pizza::box()
{
cout << "装箱,";
}
void Pizza::display()
{
cout << m_type << "制作好了!" << endl;
}
#endif // PIZZA_H
NYStyleCheesePizza.h:
#ifndef NYSTYLECHEESEPIZZA_H
#define NYSTYLECHEESEPIZZA_H
#include "pizza.h"
class NYStyleCheesePizza : public Pizza {
public:
NYStyleCheesePizza();
};
NYStyleCheesePizza::NYStyleCheesePizza()
{
m_type = "纽约奶酪披萨";
}
#endif // NYSTYLECHEESEPIZZA_H
ChicagoStyleVeggiePizza.h:
#ifndef CHICAGOSTYLEVEGGIEPIZZA_H
#define CHICAGOSTYLEVEGGIEPIZZA_H
#include "pizza.h"
class ChicagoStyleVeggiePizza : public Pizza {
public:
ChicagoStyleVeggiePizza();
};
ChicagoStyleVeggiePizza::ChicagoStyleVeggiePizza()
{
m_type = "芝加哥蔬菜披萨";
}
#endif // CHICAGOSTYLEVEGGIEPIZZA_H
main.cpp:
/*
* 工厂方法模式
*
* date:2023-9-8
*/
#include "NYPizzaStore.h"
#include "ChicagoPizzaStore.h"
int main()
{
cout << "订购一个纽约风味的奶酪披萨" << endl;
PizzaStore *pizzaStore = new NYPizzaStore();
Pizza *pizza = pizzaStore->orderPizza("cheese");
pizza->display();
cout << "\n芝加哥风味的披萨店加盟,可以订购芝加哥风味的披萨了\n" << endl;
cout << "订购一个芝加哥风味的蔬菜披萨" << endl;
pizzaStore = new ChicagoPizzaStore();
pizza = pizzaStore->orderPizza("veggie");
pizza->display();
}
运行结果: