设计模式之工厂模式C++实现
Posted 今天也要努力搬砖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之工厂模式C++实现相关的知识,希望对你有一定的参考价值。
参考书籍《Head First设计模式》
提到工厂模式有三种比较容易混淆的模式,分别是简单工厂模式、工厂方法模式和抽象工厂模式。
相同点:简单工厂,工厂方法,抽象工厂都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽取了出来,优化了系统的架构,并且增强了系统的扩展性。
它们之间的区别是:工厂方法模式用的是继承,即利用工厂方法创建对象时,需要扩展一个类,并覆盖它的工厂方法。抽象工厂模式是通过对象的组合,抽象工厂提供一个用来创建一个产品家族的抽象类型,这个类型的子类定义了产品被产生的方法。要想使用这个工厂,必须先实例化它,然后将它传入一些针对抽象类型所写的代码中。
浅谈简单工厂,工厂方法,抽象工厂的区别和使用 - 程序猿灿林 - 博客园
简单工厂 : 用来生产同一等级结构中的任意产品。(对于增加新的产品,无能为力)
工厂方法 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)
一、简单工厂(静态工厂)模式
简单工厂其实不是一个设计模式,反而比较像是一种编程习惯。但由于经常被使用,很多地方也都把它叫做设计模式。
简单工厂通过实例化一个工厂类,来获取对应的产品实例。我们不需要关注产品本身如何被创建的细节,只需要通过相应的工厂就可以获得相应的实例。
简单工厂模式的工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的对象实例。
1.1 简单工厂模式的类图
简单工厂模式的类图如下,图片链接工厂模式--简单工厂模式 - 简书,侵删
Factory工厂类,简单工厂模式的核心。其包含一个创建产品的方法,负责创建具体的产品,一般为静态函数。一般接收参数为枚举类型,通过枚举值确定创建哪一个具体产品,返回一个抽象产品IProduct的指针。客户端通过返回的指针调用产品的一些公共接口。
IProduct产品基类,简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
Product具体产品类。工厂方法种创建出的就是该类型的对象。
1.2 案列描述
披萨店可以生产各种口味的披萨,比如cheese口味,greek口味和pepperoni口味。披萨生产出来后需要准备、烘烤、切片、装盒的工作。
1.3 代码实现
声明:类的声明和实现在同一个文件里是个坏习惯,坏习惯,坏习惯,但因为我懒,还是写一起了,大家不要效仿,要引以为戒,要引以为戒,要引以为戒。
首先定义披萨类基类Pissa(就是类图中的IProduct类),和具体披萨类CheesePizza和PepperoniPizza(对应于类图中的Product),代码如下。
//披萨类
class Pizza{
public:
void prepare()
{
cout << "Preparing " << m_name << "..." << endl;
cout << "Tossing " << m_name << "..." << endl;
cout << "Add " << m_sauce<< "..." << endl;
cout << "Add toppings: ";
for (vector<string>::iterator it = m_toppings.begin(); it != m_toppings.end(); it++)
{
cout << " " << *it;
}
cout << endl;
}
void bake()
{
cout << "Bake for 25 minutes at 350 "<< endl;;
}
void cut()
{
cout << "Cutting the pizza into diagonal slices" << endl;;
}
void box()
{
cout << "Place pizza in official pizzaStore box " << endl;;
}
string getName()
{
return m_name;
}
protected:
string m_name;
string m_dough;
string m_sauce;
vector<string>m_toppings;
};
//具体披萨
class CheesePizza :public Pizza
{
public:
CheesePizza()
{
m_name = "Cheese Pizza";
m_dough = "Thin crust dough";
m_sauce = "Marinara Sauce";
m_toppings.push_back("Grated Reggiano Cheese");
}
};
class PepperoniPizza :public Pizza
{
public:
PepperoniPizza()
{
m_name = "Pepperoni Pizza";
m_dough = "Thick crust dough";
m_sauce = "Plum tomato sauce";
m_toppings.push_back("Pepperoni");
}
};
然后是简单披萨工厂类SimplePizzaFactory(对应于类图中的Factory),其包含一个静态方法来生产具体披萨。代码如下
//披萨工厂
class SimplePizzaFactory{
public:
static Pizza* CreatePizza(string pizzaType)
{
Pizza* pizza = nullptr;
if (pizzaType == "cheese")
pizza = new CheesePizza();
else if (pizzaType == "pepperoni")
pizza = new PepperoniPizza();
return pizza;
}
};
接下来就是使用工厂的代码了。定义披萨店类,其包含一个披萨工厂的指针,使用该工厂生产披萨,代码如下
//测试代码
//使用披萨工厂生产披萨
class PizzaStore
{
public:
PizzaStore(SimplePizzaFactory* factory)
{
m_factory = factory;
}
Pizza* OrderPizza(string pizzaType)
{
Pizza* pizza = m_factory->CreatePizza(pizzaType);
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box();
return pizza;
}
private:
SimplePizzaFactory* m_factory;
};
最后,在main函数中使用PissaStroe对象定一个cheese披萨和一个pepperoni披萨。代码如下
//测试代码
int main()
{
SimplePizzaFactory factory;
PizzaStore pizzaStore(&factory);
Pizza* pizza = pizzaStore.OrderPizza("cheese");
cout << "Order a " << pizza->getName()<<endl<<endl;
pizza = pizzaStore.OrderPizza("pepperoni");
cout << "Order a " << pizza->getName() << endl;
system("pause");
}
1.4 运行结果
二、工厂方法模式
工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
工厂方法用来处理对象的创建,并将这样的行为封装在子类中。这样客户关于超类的代码就和子类对象创建代码解耦了。
2.1 工厂方法模式类图
工厂方法模式类图如下, 图片链接Carson带你学设计模式:工厂方法模式(Factory Method)_Carson带你学Android-CSDN博客_工厂方法类图,侵删
与简单工厂模式的不同之处是,简单工厂是在工厂类的方法中处理对象的创建,而工厂方法模式是将针对具体对象的处理封装在子类中。这样就优化了简单工厂中内聚性低的缺点。
2.2 案列描述
继续1.2中的案例,披萨店要开两个分店,纽约披萨店和芝加哥披萨店。每个分店因为区域差异,需要的披萨口味不同,就需要用当地的工厂生产披萨。
2.3 代码实现
首先定义披萨类基类Pissa(就是类图中的Product类)这个与简单工厂中一样,然后是具体披萨类NYStyleCheesePizza、NYStylePepperoniPizza、ChicagoStyleCheesePizza、和ChicagoStylePepperoniPizza(对应于类图中的ProductA或ProductB),代码如下。
//披萨类
class Pizza{
public:
void prepare()
{
cout << "Preparing " << m_name << "..." << endl;
cout << "Tossing " << m_name << "..." << endl;
cout << "Add " << m_sauce << "..." << endl;
cout << "Add toppings: ";
for (vector<string>::iterator it = m_toppings.begin(); it != m_toppings.end(); it++)
{
cout << " " << *it;
}
cout << endl;
}
void bake()
{
cout << "Bake for 25 minutes at 350 " << endl;;
}
void cut()
{
cout << "Cutting the pizza into diagonal slices" << endl;;
}
void box()
{
cout << "Place pizza in official pizzaStore box " << endl;;
}
string getName()
{
return m_name;
}
protected:
string m_name;
string m_dough;
string m_sauce;
vector<string>m_toppings;
};
//纽约风味奶酪披萨
class NYStyleCheesePizza :public Pizza
{
public:
NYStyleCheesePizza()
{
m_name = "NY Style Cheese Pizza";
m_dough = "Thin crust dough";
m_sauce = "Marinara Sauce";
m_toppings.push_back("Grated Reggiano Cheese");
}
};
//纽约风味Pepperoni披萨
class NYStylePepperoniPizza :public Pizza
{
public:
NYStylePepperoniPizza()
{
m_name = "NY Style Pepperoni Pizza";
m_dough = "Thick crust dough";
m_sauce = "Plum tomato sauce";
m_toppings.push_back("A lot Pepperoni");
}
};
//芝加哥风味奶酪披萨
class ChicagoStyleCheesePizza :public Pizza
{
public:
ChicagoStyleCheesePizza()
{
m_name = "Chicago Style Cheese Pizza";
m_dough = "Extra Thik crust dough";
m_sauce = "Plum Tomato Sauce";
m_toppings.push_back("Shredded Mozzarella Cheese");
}
};
//芝加哥风味Pepperoni披萨
class ChicagoStylePepperoniPizza :public Pizza
{
public:
ChicagoStylePepperoniPizza()
{
m_name = "Chicago Style Pepperoni Pizza";
m_dough = "Thick crust dough";
m_sauce = "Plum tomato sauce";
m_toppings.push_back("A little Pepperoni");
}
};
然后是披萨店和各个区域的披萨分店即PizzaStore类(对应与类图中的Factory),该类中声包含一个纯虚函数CreatePizza,即工厂方法。 NYPizzaStore和ChicagoPizzaStore(对应与类图中的FactoryA和FactoryB即具体工厂,负责生产具体的披萨)继承自PizzaStore,实现工厂方法CreatePizza
。代码如下
//披萨店
class PizzaStore
{
public:
Pizza* OrderPizza(string pizzaType)
{
Pizza* pizza = CreatePizza(pizzaType);
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box();
return pizza;
}
//与简单工厂相比,实例化披萨的责任被移到一个方法,此方法如同是一个工厂。
virtual Pizza* CreatePizza(string pizzaType) = 0;
};
//纽约披萨分店
class NYPizzaStore :public PizzaStore
{
public:
virtual Pizza* CreatePizza(string pizzaType)
{
if (pizzaType == "cheese")
return new NYStyleCheesePizza();
else if (pizzaType == "pepperoni")
return new NYStylePepperoniPizza();
else
return nullptr;
}
};
//芝加哥披萨分店
class ChicagoPizzaStore :public PizzaStore
{
public:
virtual Pizza* CreatePizza(string pizzaType)
{
if (pizzaType == "cheese")
return new ChicagoStyleCheesePizza();
else if (pizzaType == "pepperoni")
return new ChicagoStylePepperoniPizza();
else
return nullptr;
}
};
最后是测试代码。首先实例化两个不同的披萨店,然后用不同的店订不同风味的奶酪披萨。代码如下
//测试代码
int main()
{
PizzaStore* nyStore = new NYPizzaStore();
PizzaStore* chicagoStore = new ChicagoPizzaStore();
Pizza* pizza = nyStore->OrderPizza("cheese");
cout << "Order a " << pizza->getName() << endl << endl;
delete pizza;
pizza = chicagoStore->OrderPizza("cheese");
cout << "Order a " << pizza->getName() << endl;
delete nyStore;
delete chicagoStore;
delete pizza;
system("pause");
}
2.4 运行结果
三、抽象工厂模式
抽象工厂是应对产品族概念的。比如说,每个汽车公司可能要同时生产轿车,货车,客车,那么每一个工厂都要有创建轿车,货车和客车的方法。
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
抽象工厂的任务是定义一个负责创建一组产品的接口。这个接口内的每个方法都负责创建一个具体产品,同时我们利用实现抽象工厂的子类来提供这些具体的做法。所以,在抽象工厂中利用工厂方法实现生产方法是相当自然的做法。
3.1 抽象工厂模式类图
抽象工厂模式类图如下, 图片链接设计模式:简单工厂、工厂方法、抽象工厂之小结与区别_superbeck的专栏-CSDN博客_简单工厂模式,工厂方法模式,抽象工厂模式,侵删
3.2 案列描述
继续2.2中的案例,披萨店想要扩展自己的业务,除了生产披萨,也开始生产蛋糕(这样的店看上去不伦不类,因为是我瞎编的,哈哈哈)。每个不同区域的披萨工厂可以生产当地风味的披萨和蛋糕(披萨和蛋糕是两个不同的产品族)。
3.3 代码实现
#include <string>
#include <vector>
#include <iostream>
using namespace std;
//披萨类
class Pizza{
public:
void prepare()
{
cout << "Preparing " << m_name << "..." << endl;
cout << "Tossing " << m_name << "..." << endl;
cout << "Add " << m_sauce << "..." << endl;
cout << "Add toppings: ";
for (vector<string>::iterator it = m_toppings.begin(); it != m_toppings.end(); it++)
{
cout << " " << *it;
}
cout << endl;
}
void bake()
{
cout << "Bake for 25 minutes at 350 " << endl;;
}
void cut()
{
cout << "Cutting the pizza into diagonal slices" << endl;;
}
void box()
{
cout << "Place pizza in official pizzaStore box " << endl;;
}
string getName()
{
return m_name;
}
protected:
string m_name;
string m_dough;
string m_sauce;
vector<string>m_toppings;
};
//纽约风味奶酪披萨
class NYStyleCheesePizza :public Pizza
{
public:
NYStyleCheesePizza()
{
m_name = "NY Style Cheese Pizza";
m_dough = "Thin crust dough";
m_sauce = "Marinara Sauce";
m_toppings.push_back("Grated Reggiano Cheese");
}
};
//纽约风味Pepperoni披萨
class NYStylePepperoniPizza :public Pizza
{
public:
NYStylePepperoniPizza()
{
m_name = "NY Style Pepperoni Pizza";
m_dough = "Thick crust dough";
m_sauce = "Plum tomato sauce";
m_toppings.push_back("A lot Pepperoni");
}
};
//芝加哥风味奶酪披萨
class ChicagoStyleCheesePizza :public Pizza
{
public:
ChicagoStyleCheesePizza()
{
m_name = "Chicago Style Cheese Pizza";
m_dough = "Extra Thik crust dough";
m_sauce = "Plum Tomato Sauce";
m_toppings.push_back("Shredded Mozzarella Cheese");
}
};
//芝加哥风味Pepperoni披萨
class ChicagoStylePepperoniPizza :public Pizza
{
public:
ChicagoStylePepperoniPizza()
{
m_name = "Chicago Style Pepperoni Pizza";
m_dough = "Thick crust dough";
m_sauce = "Plum tomato sauce";
m_toppings.push_back("A little Pepperoni");
}
};
class Cake
{
public:
string getName()
{
return m_name;
}
void bake()
{
cout << "Bake for 15 minutes at 130 " << endl;;
}
void box()
{
cout << "Place cake in official cake box " << endl;;
}
protected:
string m_name;
};
//纽约风味甜饼
class NYStyleSweetCake :public Cake
{
public:
NYStyleSweetCake()
{
m_name = "NY Style Sweet Cake";
}
};
//纽约风味咸饼
class NYStyleSaltyCake :public Cake
{
public:
NYStyleSaltyCake()
{
m_name = "NY Style salty cake";
}
};
//芝加哥风味甜饼
class ChicagoStyleSweetCake :public Cake
{
public:
ChicagoStyleSweetCake()
{
m_name = "Chicago Style Sweet Cake";
}
};
//芝加哥风味咸饼
class ChicagoStyleSaltyCake :public Cake
{
public:
ChicagoStyleSaltyCake()
{
m_name = "Chicago Style salty cake";
}
};
//测试代码
//披萨店
class PizzaStore
{
public:
Pizza* OrderPizza(string pizzaType)
{
Pizza* pizza = CreatePizza(pizzaType);
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box();
return pizza;
}
Cake* OrderCake(string cakeType)
{
Cake* cake = CreateCake(cakeType);
cake->bake();
cake->box();
return cake;
}
//与简单工厂相比,实例化披萨的责任被移到一个方法,此方法如同是一个工厂。
virtual Pizza* CreatePizza(string pizzaType) = 0;
virtual Cake* CreateCake(string cakeType) = 0;
};
//纽约披萨分店
class NYPizzaStore :public PizzaStore
{
public:
virtual Pizza* CreatePizza(string pizzaType)
{
if (pizzaType == "cheese")
return new NYStyleCheesePizza();
else if (pizzaType == "pepperoni")
return new NYStylePepperoniPizza();
else
return nullptr;
}
virtual Cake* CreateCake(string cakeType)
{
if (cakeType == "sweet")
return new NYStyleSweetCake();
else if (cakeType == "salty")
return new NYStyleSaltyCake();
else
return nullptr;
}
};
//芝加哥披萨分店
class ChicagoPizzaStore :public PizzaStore
{
public:
virtual Pizza* CreatePizza(string pizzaType)
{
if (pizzaType == "cheese")
return new ChicagoStyleCheesePizza();
else if (pizzaType == "pepperoni")
return new ChicagoStylePepperoniPizza();
else
return nullptr;
}
virtual Cake* CreateCake(string cakeType)
{
if (cakeType == "sweet")
return new ChicagoStyleSweetCake();
else if (cakeType == "salty")
return new ChicagoStyleSaltyCake();
else
return nullptr;
}
};
//测试代码
int main()
{
PizzaStore* nyStore = new NYPizzaStore();
PizzaStore* chicagoStore = new ChicagoPizzaStore();
Pizza* pizza = nyStore->OrderPizza("cheese");
cout << "Order a " << pizza->getName() << endl;
Cake* cake = nyStore->OrderCake("sweet");
cout << "Order a " << cake->getName() << endl<<endl;
delete pizza;
delete cake;
pizza = chicagoStore->OrderPizza("cheese");
cout << "Order a " << pizza->getName() << endl;
cake = chicagoStore->OrderCake("sweet");
cout << "Order a " << cake->getName() << endl;
delete nyStore;
delete chicagoStore;
delete pizza;
system("pause");
}
输出结果
ps:三个模式放在一起写,就一不小心又臭又长了。
以上是关于设计模式之工厂模式C++实现的主要内容,如果未能解决你的问题,请参考以下文章