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