设计模式系列(六)抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式提供了一个接口,用于创建相关或依赖对象的家族,即产品族,而不需要明确指定具体类。这里利用了依赖倒置原则,即依赖抽象,不要依赖具体。注意到,抽象工厂模式创建的是一个产品族,而不单单是一个产品,这一点是与工厂方法模式不同的。
抽象工厂模式一般需要四个角色,这四个角色与工厂方法模式的基本相同:
(1)抽象工厂角色:这里可以说是一个标准的接口,定义了所有产品的创建方法,形成一个产品族,等待被实现。在java中它由抽象类或者接口来实现,在C++中由抽象类实现。
(2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象,这里具体类的实现也是一个产品族,每个产品使用的是类似于工厂方法模式的形式来创建。
(3)抽象产品角色:这里一般是接口,定义了一种产品的接口,每个产品有自己不同的接口。在java中一般有抽象类或者接口来实现,在C++中由抽象类实现。
(4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例,每个产品可以有很多具体类,注意这里的一族产品和一种产品的不同具体类是不一样的。
(2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象,这里具体类的实现也是一个产品族,每个产品使用的是类似于工厂方法模式的形式来创建。
(3)抽象产品角色:这里一般是接口,定义了一种产品的接口,每个产品有自己不同的接口。在java中一般有抽象类或者接口来实现,在C++中由抽象类实现。
(4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例,每个产品可以有很多具体类,注意这里的一族产品和一种产品的不同具体类是不一样的。
可以看出,这些角色与工厂方法基本一样,那么它们之间的区别在哪里?
(1)抽象工厂模式创建的是一族产品,而工厂方法创建的是一个产品,抽象工厂模式里面其实使用了工厂方法模式,对于每一个产品的创建,其实和工厂方法模式十分类似;
(2)抽象工厂模式采用的是对象组合,将各种产品组合在一个工厂里面,然后由具体类实现,对象的创建被实现在工厂接口所暴露出来的方法中,而工厂方法模式则使用继承,把对象的创建委托给子类,子类实现工厂方法来创建对象;
(3)当需要创建产品家族和想制造相关产品的集合时,可以使用抽象工厂模式,而工厂方法可以把客户代码实例化的具体类中解耦,其使用方式很简单,只需要继承成子类,并实现工厂方法即可;
(4)抽象工厂模式更为复杂,工厂方法模式相对于比较简单。
使用抽象工厂模式还要满足下述条件:
(1)系统中有多个产品族,而系统一次只可能消费其中一族产品。
(1)系统中有多个产品族,而系统一次只可能消费其中一族产品。
(2)同属于同一个产品族的产品以其使用。
这里需要特别说明一下产品族,它是指位于不同产品等级结构中,功能相关联的产品组成的家族。一般是位于不同的等级结构中的相同位置上。显然,每一个产品族中含有产品的数目,与产品等级结构的数目是相等的,形成一个二维的坐标系,水平坐标是产品等级结构,纵坐标是产品族。叫做相图。当有多个不同的等级结构的产品时,如果使用工厂方法模式就势必要使用多个独立的工厂等级结构来对付这些产品的等级结构。如果这些产品等级结构是平行的,会导致多个平行的工厂等级结构。抽象工厂模式使用同一个 工厂等级结构负责这些不同产品等级结构产品对象的创建。对于每一个产品族,都有一个具体工厂。而每一个具体工厂创建属于同一个产品族,但是分属于不同等级结构的产品。通过引进抽象工厂模式,可以处理具有相同(或者相似)等级结构的多个产品族中的产品对象的创建问题。由于每个具体工厂角色都需要负责两个不同等级结构的产品对象的创建,因此每个工厂角色都需要提供两个工厂方法,分别用于创建两个等级结构的产品。既然每个具体工厂角色都需要实现这两个工厂方法,所以具有一般性,不妨抽象出来,移动到抽象工厂角色中加以声明。
抽象工厂模式的优点:它分离了具体的类;它使得易于交换产品系列;它有利于产品的一致性。
抽象工厂模式的缺点:难以支持新种类的产品。
在以下情况下应当考虑使用抽象工厂模式:
(1)一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
(2)这个系统有多于一个的产品族,而系统只消费其中某一产品族。
(3)同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
(4)系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
(2)这个系统有多于一个的产品族,而系统只消费其中某一产品族。
(3)同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
(4)系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
下面我们来看一个十分详细的例子,这个例子包括的文件依次是:AbstractFactoryPattern.h、AbstractFactoryPattern.cpp、AbstractFactoryPatternTest.cpp。
// 抽象工厂模式
#ifndef ABSTRACTFACTORY
#define ABSTRACTFACTORY
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
using std::string;
using std::vector;
using std::cout;
using std::endl;
// 需要在抽象工厂内创建的产品的抽象产品:调味料和添加品
class Dough // 面团
{
public:
Dough(){}
virtual ~Dough(){}
virtual string DoughKind() = 0;
};
class Sauce // 酱油
{
public:
Sauce(){}
virtual ~Sauce(){}
virtual string SauceKind() = 0;
};
class Cheese // 奶酪
{
public:
Cheese(){}
virtual ~Cheese(){}
virtual string CheeseKind() = 0;
};
class Clams // 蛤蚌
{
public:
Clams(){}
virtual ~Clams(){}
virtual string ClamsKind() = 0;
};
class Veggies // 蔬菜
{
public:
Veggies(){}
virtual ~Veggies(){}
virtual string VeggiesKind() = 0;
};
class Pepperoni // 腊香肠
{
public:
Pepperoni(){}
virtual ~Pepperoni(){}
virtual string PepperoniKind() = 0;
};
// 需要在抽象工厂内创建的产品的具体产品:调味料和添加品
// 面团
class ThickCrustDough : public Dough
{
public:
string DoughKind();
};
class ThinCrustDough : public Dough
{
public:
string DoughKind();
};
// 酱油
class MarinaraSauce : public Sauce
{
public:
string SauceKind();
};
class PlumTomatoSauce : public Sauce
{
public:
string SauceKind();
};
// 奶酪
class ReggianoCheese : public Cheese
{
public:
string CheeseKind();
};
class ParmesanCheese : public Cheese
{
public:
string CheeseKind();
};
class MozzarellaCheese : public Cheese
{
public:
string CheeseKind();
};
// 蛤蚌
class FreshClams : public Clams
{
public:
string ClamsKind();
};
class FrozenClams : public Clams
{
public:
string ClamsKind();
};
// 蔬菜
class BlackOlives : public Veggies
{
public:
string VeggiesKind();
};
class Eggplant : public Veggies
{
public:
string VeggiesKind();
};
class Garlic : public Veggies
{
public:
string VeggiesKind();
};
class Mushroom : public Veggies
{
public:
string VeggiesKind();
};
class Onion : public Veggies
{
public:
string VeggiesKind();
};
class RedPepper : public Veggies
{
public:
string VeggiesKind();
};
class Spinach : public Veggies
{
public:
string VeggiesKind();
};
// 腊香肠
class SlicedPepperoni : public Pepperoni
{
public:
string PepperoniKind();
};
// 用于制造上述配料和添加品的抽象工厂---原料工厂,用于创建原料产品族
class PizzaIngredientFactory
{
public:
PizzaIngredientFactory(){}
virtual ~PizzaIngredientFactory(){}
virtual Dough* createDough() = 0;
virtual Sauce* createSauce() = 0;
virtual Cheese* createCheese() = 0;
virtual vector<Veggies*> createVeggies() = 0;
virtual Pepperoni* createPepperoni() = 0;
virtual Clams* createClam() = 0;
};
// 原料工厂的具体类,即具体的原料工厂,扮演者抽象工厂模式中的具体工厂角色
// 芝加哥的原料工厂
class ChicagoPizzaIngredientFactory : public PizzaIngredientFactory
{
public:
Dough* createDough();
Sauce* createSauce();
Cheese* createCheese();
vector<Veggies*> createVeggies();
Pepperoni* createPepperoni();
Clams* createClam();
};
// 纽约的原料工厂
class NYPizzaIngredientFactory : public PizzaIngredientFactory
{
public:
Dough* createDough();
Sauce* createSauce();
Cheese* createCheese();
vector<Veggies*> createVeggies();
Pepperoni* createPepperoni();
Clams* createClam();
};
// 需要用工厂方法模式创建的抽象产品类:比萨(其中需要用到抽象工厂创建的调料产品族)
class Pizza
{
public:
string name;
Dough* dough;
Sauce* sauce;
vector<Veggies*> veggies;
Cheese* cheese;
Pepperoni* pepperoni;
Clams* clam;
Pizza()
{
dough = NULL;
sauce = NULL;
cheese = NULL;
pepperoni = NULL;
clam = NULL;
veggies.clear();
}
virtual ~Pizza()
{
cout << "释放原料指针" << endl;
if (dough != NULL)
{
delete dough;
dough = NULL;
}
if (sauce != NULL)
{
delete sauce;
sauce = NULL;
}
if (cheese != NULL)
{
delete cheese;
cheese = NULL;
}
if (pepperoni != NULL)
{
delete pepperoni;
pepperoni = NULL;
}
if (clam != NULL)
{
delete clam;
clam = NULL;
}
for (size_t i = 0; i < veggies.size(); ++i)
{
if (veggies.at(i) != NULL)
{
delete veggies.at(i);
veggies.at(i) = NULL;
}
}
veggies.clear();
}
virtual void prepare() = 0;
string getName();
void setName(string name);
void bake();
void cut();
void box();
string toString();
};
// 需要用工厂方法模式创建的具体产品类:各种类的比萨(其中需要用到抽象工厂创建的调料产品族)
class CheesePizza : public Pizza
{
public:
PizzaIngredientFactory* ingredientFactory;
CheesePizza(PizzaIngredientFactory* pf)
{
this->ingredientFactory = pf;
}
~CheesePizza()
{
cout << "释放CheesePizza中的原料工厂指针" << endl;
if (ingredientFactory != NULL)
{
delete ingredientFactory;
ingredientFactory = NULL;
}
}
void prepare();
};
class ClamPizza : public Pizza
{
public:
PizzaIngredientFactory* ingredientFactory;
ClamPizza(PizzaIngredientFactory* pf)
{
this->ingredientFactory = pf;
}
~ClamPizza()
{
cout << "释放ClamPizza中的原料工厂指针" << endl;
if (ingredientFactory != NULL)
{
delete ingredientFactory;
ingredientFactory = NULL;
}
}
void prepare();
};
class PepperoniPizza : public Pizza
{
public:
PizzaIngredientFactory* ingredientFactory;
PepperoniPizza(PizzaIngredientFactory* pf)
{
this->ingredientFactory = pf;
}
~PepperoniPizza()
{
cout << "释放PepperoniPizza中的原料工厂指针" << endl;
if (ingredientFactory != NULL)
{
delete ingredientFactory;
ingredientFactory = NULL;
}
}
void prepare();
};
class VeggiePizza : public Pizza
{
public:
PizzaIngredientFactory* ingredientFactory;
VeggiePizza(PizzaIngredientFactory* pf)
{
this->ingredientFactory = pf;
}
~VeggiePizza()
{
cout << "释放VeggiePizza中的原料工厂指针" << endl;
if (ingredientFactory != NULL)
{
delete ingredientFactory;
ingredientFactory = NULL;
}
}
void prepare();
};
// 需要用工厂方法模式创建的抽象工厂类:卖比萨的商店
class PizzaStore
{
public:
PizzaStore(){}
virtual ~PizzaStore(){}
virtual Pizza* createPizza(string item) = 0;
Pizza* orderPizza(string item);
};
// 需要用工厂方法模式创建的具体工厂类:各地区卖比萨的商店
class ChicagoPizzaStore : public PizzaStore
{
public:
virtual Pizza* createPizza(string item);
};
class NYPizzaStore : public PizzaStore
{
public:
virtual Pizza* createPizza(string item);
};
#endif
#include "AbstractFactoryPattern.h"
// 需要在抽象工厂内创建的产品的具体产品:调味料和添加品
// 面团
string ThickCrustDough::DoughKind()
{
return "ThickCrust style extra thick crust dough";
}
string ThinCrustDough::DoughKind()
{
return "Thin Crust Dough";
}
// 酱油
string MarinaraSauce::SauceKind()
{
return "Marinara Sauce";
}
string PlumTomatoSauce::SauceKind()
{
return "Tomato sauce with plum tomatoes";
}
// 奶酪
string ReggianoCheese::CheeseKind()
{
return "Reggiano Cheese";
}
string ParmesanCheese::CheeseKind()
{
return "Shredded Parmesan";
}
string MozzarellaCheese::CheeseKind()
{
return "Shredded Mozzarella";
}
// 蛤蚌
string FreshClams::ClamsKind()
{
return "Fresh Clams from Long Island Sound";
}
string FrozenClams::ClamsKind()
{
return "Frozen Clams from Chesapeake Bay";
}
// 蔬菜
string BlackOlives::VeggiesKind()
{
return "Black Olives";
}
string Eggplant::VeggiesKind()
{
return "Eggplant";
}
string Garlic::VeggiesKind()
{
return "Garlic";
}
string Mushroom::VeggiesKind()
{
return "Mushrooms";
}
string Onion::VeggiesKind()
{
return "Onion";
}
string RedPepper::VeggiesKind()
{
return "Red Pepper";
}
string Spinach::VeggiesKind()
{
return "Spinach";
}
// 腊香肠
string SlicedPepperoni::PepperoniKind()
{
return "Sliced Pepperoni";
}
// 原料工厂的具体类,即具体的原料工厂,扮演者抽象工厂模式中的具体工厂角色
// 芝加哥的原料工厂
Dough* ChicagoPizzaIngredientFactory::createDough()
{
return new ThickCrustDough();
}
Sauce* ChicagoPizzaIngredientFactory::createSauce()
{
return new PlumTomatoSauce();
}
Cheese* ChicagoPizzaIngredientFactory::createCheese()
{
return new MozzarellaCheese();
}
vector<Veggies*> ChicagoPizzaIngredientFactory::createVeggies()
{
vector<Veggies*> vec;
vec.push_back(new BlackOlives());
vec.push_back(new Spinach());
vec.push_back(new Eggplant());
return vec;
}
Pepperoni* ChicagoPizzaIngredientFactory::createPepperoni()
{
return new SlicedPepperoni();
}
Clams* ChicagoPizzaIngredientFactory::createClam()
{
return new FrozenClams();
}
// 纽约的原料工厂
Dough* NYPizzaIngredientFactory::createDough()
{
return new ThinCrustDough();
}
Sauce* NYPizzaIngredientFactory::createSauce()
{
return new MarinaraSauce();
}
Cheese* NYPizzaIngredientFactory::createCheese()
{
return new ReggianoCheese();
}
vector<Veggies*> NYPizzaIngredientFactory::createVeggies()
{
vector<Veggies*> vec;
vec.push_back(new Garlic());
vec.push_back(new Onion());
vec.push_back(new Mushroom());
vec.push_back(new RedPepper());
return vec;
}
Pepperoni* NYPizzaIngredientFactory::createPepperoni()
{
return new SlicedPepperoni();
}
Clams* NYPizzaIngredientFactory::createClam()
{
return new FreshClams();
}
// 需要用工厂方法模式创建的抽象产品类:比萨(其中需要用到抽象工厂创建的调料产品族)
string Pizza::getName()
{
return name;
}
void Pizza::setName(string name)
{
this->name = name;
}
void Pizza::bake()
{
cout << "Bake for 25 minutes at 350" << endl;
}
void Pizza::cut()
{
cout << "Cutting the pizza into diagonal slices" << endl;
}
void Pizza::box()
{
cout << "Place pizza in official PizzaStore box" << endl;
}
string Pizza::toString()
{
string result;
result.append("---- " + name + " ----\n");
if (dough != NULL)
{
result.append(dough->DoughKind());
result.append("\n");
}
if (sauce != NULL)
{
result.append(sauce->SauceKind());
result.append("\n");
}
if (cheese != NULL)
{
result.append(cheese->CheeseKind());
result.append("\n");
}
if (!veggies.empty())
{
for (size_t i = 0; i < veggies.size(); i++)
{
result.append(veggies[i]->VeggiesKind());
if (i < veggies.size() - 1)
{
result.append(", ");
}
}
result.append("\n");
}
if (clam != NULL)
{
result.append(clam->ClamsKind());
result.append("\n");
}
if (pepperoni != NULL)
{
result.append(pepperoni->PepperoniKind());
result.append("\n");
}
return result;
}
// 需要用工厂方法模式创建的具体产品类:各种类的比萨(其中需要用到抽象工厂创建的调料产品族)
void CheesePizza::prepare()
{
cout << "Preparing " << name << endl;
dough = ingredientFactory->createDough();
sauce = ingredientFactory->createSauce();
cheese = ingredientFactory->createCheese();
}
void ClamPizza::prepare()
{
cout << "Preparing " << name << endl;
dough = ingredientFactory->createDough();
sauce = ingredientFactory->createSauce();
cheese = ingredientFactory->createCheese();
clam = ingredientFactory->createClam();
}
void PepperoniPizza::prepare()
{
cout << "Preparing " << name << endl;
dough = ingredientFactory->createDough();
sauce = ingredientFactory->createSauce();
cheese = ingredientFactory->createCheese();
veggies = ingredientFactory->createVeggies();
pepperoni = ingredientFactory->createPepperoni();
}
void VeggiePizza::prepare()
{
cout << "Preparing " << name << endl;
dough = ingredientFactory->createDough();
sauce = ingredientFactory->createSauce();
cheese = ingredientFactory->createCheese();
veggies = ingredientFactory->createVeggies();
}
// 需要用工厂方法模式创建的抽象工厂类:卖比萨的商店
Pizza* PizzaStore::orderPizza(string item)
{
Pizza* pizza = createPizza(item); // 这里是工厂方法,创建对象延迟到子类
cout << "--- Making a " << pizza->getName() << " ---" << endl;
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box();
return pizza;
}
// 需要用工厂方法模式创建的具体工厂类:各地区卖比萨的商店
Pizza* ChicagoPizzaStore::createPizza(string item)
{
Pizza* pizza = NULL;
PizzaIngredientFactory* ingredientFactory = new ChicagoPizzaIngredientFactory();
if (!item.compare("cheese"))
{
pizza = new CheesePizza(ingredientFactory);
pizza->setName("Chicago Style Cheese Pizza");
}
else if (!item.compare("veggie"))
{
pizza = new VeggiePizza(ingredientFactory);
pizza->setName("Chicago Style Veggie Pizza");
}
else if (!item.compare("clam"))
{
pizza = new ClamPizza(ingredientFactory);
pizza->setName("Chicago Style Clam Pizza");
}
else if (!item.compare("pepperoni"))
{
pizza = new PepperoniPizza(ingredientFactory);
pizza->setName("Chicago Style Pepperoni Pizza");
}
return pizza;
}
Pizza* NYPizzaStore::createPizza(string item)
{
Pizza* pizza = NULL;
PizzaIngredientFactory* ingredientFactory = new NYPizzaIngredientFactory();
if (!item.compare("cheese"))
{
pizza = new CheesePizza(ingredientFactory);
pizza->setName("New York Style Cheese Pizza");
}
else if (!item.compare("veggie"))
{
pizza = new VeggiePizza(ingredientFactory);
pizza->setName("New York Style Veggie Pizza");
}
else if (!item.compare("clam"))
{
pizza = new ClamPizza(ingredientFactory);
pizza->setName("New York Style Clam Pizza");
}
else if (!item.compare("pepperoni"))
{
pizza = new PepperoniPizza(ingredientFactory);
pizza->setName("New York Style Pepperoni Pizza");
}
return pizza;
}
#include "AbstractFactoryPattern.h"
void main()
{
PizzaStore* nyStore = new NYPizzaStore();
PizzaStore* chicagoStore = new ChicagoPizzaStore();
cout << "----------------------------------------------------" << endl;
Pizza* pizza = nyStore->orderPizza("cheese");
cout << "Ethan ordered a " << pizza->toString() << endl;
delete pizza;
cout << "----------------------------------------------------" << endl;
pizza = chicagoStore->orderPizza("cheese");
cout << "Joel ordered a " << pizza->toString() << endl;
delete pizza;
cout << "----------------------------------------------------" << endl;
pizza = nyStore->orderPizza("clam");
cout << "Ethan ordered a " << pizza->toString() << endl;
delete pizza;
cout << "----------------------------------------------------" << endl;
pizza = chicagoStore->orderPizza("clam");
cout << "Joel ordered a " << pizza->toString() << endl;
delete pizza;
cout << "----------------------------------------------------" << endl;
pizza = nyStore->orderPizza("pepperoni");
cout << "Ethan ordered a " << pizza->toString() << endl;
delete pizza;
cout << "----------------------------------------------------" << endl;
pizza = chicagoStore->orderPizza("pepperoni");
cout << "Joel ordered a " << pizza->toString() << endl;
delete pizza;
cout << "----------------------------------------------------" << endl;
pizza = nyStore->orderPizza("veggie");
cout << "Ethan ordered a " << pizza->toString() << endl;
delete pizza;
cout << "----------------------------------------------------" << endl;
pizza = chicagoStore->orderPizza("veggie");
cout << "Joel ordered a " << pizza->toString() << endl;
delete pizza;
delete nyStore;
delete chicagoStore;
pizza = NULL;
nyStore = NULL;
chicagoStore = NULL;
}
该例的运行结果如图1所示,这个例子中指针十分多,所以一定要注意析构函数和指针的释放。
图1 运行结果
该例的UML类图如图2所示。
图2 UML类图
从图2中可以看出,这个例子是十分复杂的。大家一定要一步步理清思路,如果能搞明白这个例子,基本上工厂模式的三种都能掌握。下面我们对其进行分析。
对于PizzaStore类和工厂方法模式的这个类是基本一样的,注意,这里的createPizza()函数其实还是一个工厂方法,所以披萨店这个高层的设计还是按照工厂方法的模式设计的,这个例子对于工厂方法那个例子只是进行了扩充和修改,至于工厂方法的例子请参考上一篇文章:点击打开链接。这个例子主要扩充的在于,我们将制作比萨的原料族用抽象工厂模式来实现,注意,这里是所有原料的创建,大家看看PizzaIngredientFactory类中的函数就会清楚,有很多创建原料的函数,每个函数都创建不同的原料,从而构成了一个原料的产品族,然后每个地区的披萨店有自己的原料工厂,从而为每个地区的披萨店提供原料。注意,这里和工厂方法的例子有一点变动,那就是披萨的具体类里面不再分纽约的披萨和芝加哥的披萨,而是只按照口味进行了区分,具体是哪里的披萨由原料工厂的原料决定。大家要格外注意,其实在PizzaIngredientFactory类中的那些函数,采用的模式可以说是工厂方法模式,所以说抽象工厂模式其实在内部还是使用了工厂方法模式,所以抽象工厂模式创建的一个产品族,而产品族中每个产品的创建可以使用工厂方法来创建。
我们主要需要明确几个类的角色和关系:
(1)PizzaIngredientFactory抽象类扮演了抽象工厂模式中抽象工厂的角色,而其具体类ChicagoPizzaIngredientFactory和NYPizzaIngredientFactory则扮演了抽象工厂模式中具体工厂的角色。
(2)图2中右侧的一大堆类都是原料的抽象类和具体类,这些类似于工厂方法模式中的抽象产品类和具体产品类。
(3)图2左上角的Pizza类及其具体类扮演了工厂方法模式中的抽象产品类和具体产品类,这里需要对应起来的就是图2右上角的PizzaStore类及其具体类扮演了工厂方法模式中的抽象工厂角色和具体工厂角色。
所以,从整体来看,这个例子其实是上一篇文章例子的扩展版,所以该例包含了工厂方法模式和抽象工厂模式。
总之,目前讲到的工厂模式中抽象工厂模式是最为复杂的模式。大家可以细细品味,代码建议大家可以自己写一遍,会发现很多自己的误区。