设计模式系列(四)简单工厂模式(Simple Factory Pattern/Static Factory Method)

设计模式系列(四)简单工厂模式

(Simple Factory Pattern/Static Factory Method)


    简单工厂模式又被成为静态工厂方法,所以其外文名一般是Static Factory Method。其属于创建型模式,本质上并不属于23种GOF设计模式之一,这种模式可以称之为一种编程习惯,算是一种比较良好的设计习惯。那么什么是简单工厂设计模式呢?从概念上来看,就知道其比较简单。简单工厂模式就是将对象的创建交给一个专门的类来处理,此类中包含一个方法,专门用来创建对象并返回创建好的对象,这个方法在JAVA中通常声明为静态方法,使得其可以直接通过类名访问。

    简单工厂模式需要具备的角色有:

(1)工厂(Creator)角色:简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
(2)抽象产品(Product)角色:简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
(3)具体产品(Concrete Product)角色:是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

    简单工厂模式的优点有工厂类是整个模式的关键。包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象。通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来。仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的,明确了各自的职责和权利,有利于整个软件体系结构的优化。

    简单工厂模式的缺点有由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;这些缺点在工厂方法模式中得到了一定的克服。

    简单工厂模式的使用场景有工厂类负责创建的对象比较少;客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。

    下面我们来看一个例子,依次是三个文件的程序:SimpleFactoryPattern.h、SimpleFactoryPattern.cpp、SimpleFactoryPatternTest.cpp。

// 简单工厂模式

#ifndef SIMPLEFACTORY
#define SIMPLEFACTORY

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>

using std::string;
using std::vector;
using std::cout;
using std::endl;
using std::fixed;
using std::setprecision;

// 抽象产品角色:比萨
class Pizza
{
protected:
	Pizza(){}	// 仅限于子类创建该对象
public:
	string name;	// 名字
	string dough;	// 面团
	string sauce;	// 酱油
	vector<string> toppings; // 调料

	virtual ~Pizza(){}
	string getName();
	void prepare();
	void bake();
	void cut();
	void box();
	string toString();
};

// 具体产品角色1
class VeggiePizza : public Pizza
{
public:
	VeggiePizza()
	{
		name = "Veggie Pizza";
		dough = "Crust";
		sauce = "Marinara sauce";
		toppings.push_back("Shredded mozzarella");
		toppings.push_back("Grated parmesan");
		toppings.push_back("Diced onion");
		toppings.push_back("Sliced mushrooms");
		toppings.push_back("Sliced red pepper");
		toppings.push_back("Sliced black olives");
	}
};

// 具体产品角色2
class ClamPizza : public Pizza
{
public:
	ClamPizza()
	{
		name = "Clam Pizza";
		dough = "Thin crust";
		sauce = "White garlic sauce";
		toppings.push_back("Clams");
		toppings.push_back("Grated parmesan cheese");
	}
};

// 具体产品角色3
class PepperoniPizza : public Pizza
{
public:
	PepperoniPizza()
	{
		name = "Pepperoni Pizza";
		dough = "Crust";
		sauce = "Marinara sauce";
		toppings.push_back("Sliced Pepperoni");
		toppings.push_back("Sliced Onion");
		toppings.push_back("Grated parmesan cheese");
	}
};

// 具体产品角色4
class CheesePizza : public Pizza
{
public:
	CheesePizza()
	{
		name = "Cheese Pizza";
		dough = "Regular Crust";
		sauce = "Marinara Pizza Sauce";
		toppings.push_back("Fresh Mozzarella");
		toppings.push_back("Parmesan");
	}
};

// 工厂角色
class SimplePizzaFactory
{
public:
	Pizza* createPizza(string type);
};

// 实际应用类
class PizzaStore
{
public:
	SimplePizzaFactory factory;

	PizzaStore(SimplePizzaFactory factory)
	{
		this->factory = factory;
	}

	Pizza* orderPizza(string type);
};

#endif

#include "SimpleFactoryPattern.h"

// 抽象产品角色:比萨
string Pizza::getName()
{
	return name;
}

void Pizza::prepare()
{
	cout << "Preparing " << name << endl;
}

void Pizza::bake()
{
	cout << "Baking " << name << endl;
}

void Pizza::cut()
{
	cout << "Cutting " << name << endl;
}

void Pizza::box()
{
	cout << "Boxing " << name << endl;
}

string Pizza::toString()
{
	// code to display pizza name and ingredients
	string display;
	display.append("---- " + name + " ----\n");
	display.append(dough + "\n");
	display.append(sauce + "\n");
	for (size_t i = 0; i < toppings.size(); i++) {
		display.append(toppings.at(i) + "\n");
	}
	return display;
}

// 工厂角色
Pizza* SimplePizzaFactory::createPizza(string type) 
{
	Pizza* pizza = NULL;

	if (!type.compare("cheese")) 
	{
		pizza = new CheesePizza();
	}
	else if (!type.compare("pepperoni"))
	{
		pizza = new PepperoniPizza();
	}
	else if (!type.compare("clam")) 
	{
		pizza = new ClamPizza();
	}
	else if (!type.compare("veggie")) 
	{
		pizza = new VeggiePizza();
	}
	return pizza;
}

// 实际应用类
Pizza* PizzaStore::orderPizza(string type)
{
	Pizza* pizza = NULL;

	pizza = factory.createPizza(type);

	pizza->prepare();
	pizza->bake();
	pizza->cut();
	pizza->box();

	return pizza;
}

#include "SimpleFactoryPattern.h"

void main()
{
	SimplePizzaFactory factory ;
	PizzaStore store(factory);

	cout << "--------------------------------------" << endl;
	Pizza* pizza = store.orderPizza("cheese");
	cout << "We ordered a " << pizza->getName() << endl;

	cout << "--------------------------------------" << endl;
	pizza = store.orderPizza("veggie");
	cout << "We ordered a " << pizza->getName() << endl;

	delete pizza;
	cout << "--------------------------------------" << endl;

}

    该程序的运行结果如图1所示。

设计模式系列(四)简单工厂模式(Simple Factory Pattern/Static Factory Method)_第1张图片
图1 运行结果

    该例的UML类图如图2所示。

设计模式系列(四)简单工厂模式(Simple Factory Pattern/Static Factory Method)_第2张图片
图2 UML类图

    从图中可以看出,Pizza类是一个抽象角色,而它的子类定义了不同的比萨类型,在SimplePizzaFactory类中,负责创建比萨对象,具体创建哪个对象由传入的string类型的值决定,而PizzaStore类中定义了定制比萨的过程,具体做什么样的比萨由工厂类里面创建的对象决定,所以从客户的角度来看,客户只需要调用orderPizza()函数,传入自己想要的比萨的简单描述,然后系统内部就会制作相应的比萨,得到了较好的封装性,在创建的对象需要改变时,只需要修改工厂类即可,客户代码不会发生改变,这个特性也十分便利。

你可能感兴趣的:(设计模式,C++,simple,简单工厂模式,factory,UML类图,Patte)