设计模式之工厂模式C++实现

Posted 今天也要努力搬砖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之工厂模式C++实现相关的知识,希望对你有一定的参考价值。

参考书籍《Head First设计模式》

参考文章:设计模式:简单工厂、工厂方法、抽象工厂之小结与区别_superbeck的专栏-CSDN博客_简单工厂模式,工厂方法模式,抽象工厂模式简单工厂,工厂方法,抽象工厂都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽取了出来,优化了系统的架构,并且增强了系统的扩展性。本文是本人对这三种模式学习后的一个小结以及对他们之间的区别的理解。 简单工厂简单工厂模式的工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的对象实例。不修改代码的话,是无法扩展的。  工厂https://blog.csdn.net/superbeck/article/details/4446177

        提到工厂模式有三种比较容易混淆的模式,分别是简单工厂模式、工厂方法模式和抽象工厂模式。

相同点:简单工厂,工厂方法,抽象工厂都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽取了出来,优化了系统的架构,并且增强了系统的扩展性。

它们之间的区别是:工厂方法模式用的是继承,即利用工厂方法创建对象时,需要扩展一个类,并覆盖它的工厂方法。抽象工厂模式是通过对象的组合,抽象工厂提供一个用来创建一个产品家族的抽象类型,这个类型的子类定义了产品被产生的方法。要想使用这个工厂,必须先实例化它,然后将它传入一些针对抽象类型所写的代码中。

浅谈简单工厂,工厂方法,抽象工厂的区别和使用 - 程序猿灿林 - 博客园

简单工厂 : 用来生产同一等级结构中的任意产品。(对于增加新的产品,无能为力)

工厂方法 :用来生产同一等级结构中的固定产品。(支持增加任意产品)  
抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)  

一、简单工厂(静态工厂)模式

        简单工厂其实不是一个设计模式,反而比较像是一种编程习惯。但由于经常被使用,很多地方也都把它叫做设计模式。

         简单工厂通过实例化一个工厂类,来获取对应的产品实例。我们不需要关注产品本身如何被创建的细节,只需要通过相应的工厂就可以获得相应的实例。

        简单工厂模式的工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的对象实例。

 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++实现的主要内容,如果未能解决你的问题,请参考以下文章

工厂模式C++实现

C++ 常用设计模式之 简单工厂模式

C++进阶系列之设计模式---设计模式的核心思想

C++之工厂(factory)模式

C++设计模式之-工厂模式的总结

设计模式之抽象工厂模式(C++)