您的位置:首页 > 编程语言 > C语言/C++

设计模式系列(五)工厂方法模式(Factory Method Pattern)

2015-12-04 16:10 453 查看

设计模式系列(五)工厂方法模式(Factory Method Pattern)

    工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到子类。所谓决定,并不是指模式允许子类本身在运行时做决定,而是指在编写创建者类时,不需要知道实际创建的产品是哪一个,选择了使用哪个子类,就自然决定了实际创建的产品是什么。这是一种常用的对象创建型设计模式,此模式的核心精神是封装类中不变的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。

    工厂方法模式对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不再负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。

    工厂方法模式主要有四个角色:

(1)抽象工厂(Creator)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。

(2)具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。在上图中有两个这样的角色:BulbCreator与TubeCreator。

(3)抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。

(4)具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。

    上一篇文章讲述了简单工厂模式。简单工厂是把全部的事情,在一个地方都处理完了,然而工厂方法却是在创建一个框架,让子类来决定要如何实现。比方说在工厂方法中下面的例子中,orderPizza()方法提供了一般的框架,以便创建比萨,orderPizza()方法依赖工厂方法创建具体类,并制造出实际的比萨。可以通过继承PizzaStore类,决定实际制造出的比萨是什么。简单工厂的做法,可以将对象的创建封装起来,但是简单工厂不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。

    下面我们来看看上面说到的例子,这个例子由三个文件组成,依次是:FactoryMethodPattern.h、FactoryMethodPattern.cpp、FactoryMethodPatternTest.cpp。

// 工厂方法模式

#ifndef FACTORYMETHOD
#define FACTORYMETHOD

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

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

// 抽象产品角色:比萨
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 ChicagoStyleClamPizza : public Pizza
{
public:
ChicagoStyleClamPizza()
{
name = "Chicago Style Clam Pizza";
dough = "Extra Thick Crust Dough";
sauce = "Plum Tomato Sauce";
toppings.push_back("Shredded Mozzarella Cheese");
toppings.push_back("Frozen Clams from Chesapeake Bay");
}

void cut();
};

// 具体产品角色---芝加哥风味的比萨2
class ChicagoStyleCheesePizza : public Pizza
{
public:
ChicagoStyleCheesePizza()
{
name = "Chicago Style Deep Dish Cheese Pizza";
dough = "Extra Thick Crust Dough";
sauce = "Plum Tomato Sauce";
toppings.push_back("Shredded Mozzarella Cheese");
}

void cut();
};

// 具体产品角色---芝加哥风味的比萨3
class ChicagoStylePepperoniPizza : public Pizza
{
public:
ChicagoStylePepperoniPizza()
{
name = "Chicago Style Pepperoni Pizza";
dough = "Extra Thick Crust Dough";
sauce = "Plum Tomato Sauce";
toppings.push_back("Shredded Mozzarella Cheese");
toppings.push_back("Black Olives");
toppings.push_back("Spinach");
toppings.push_back("Eggplant");
toppings.push_back("Sliced Pepperoni");
}

void cut();
};

// 具体产品角色---芝加哥风味的比萨4
class ChicagoStyleVeggiePizza : public Pizza
{
public:
ChicagoStyleVeggiePizza()
{
name = "Chicago Deep Dish Veggie Pizza";
dough = "Extra Thick Crust Dough";
sauce = "Plum Tomato Sauce";
toppings.push_back("Shredded Mozzarella Cheese");
toppings.push_back("Black Olives");
toppings.push_back("Spinach");
toppings.push_back("Eggplant");
}

void cut();
};

// 具体产品角色---纽约风味的比萨1
class NYStyleCheesePizza : public Pizza
{
public:
NYStyleCheesePizza()
{
name = "NY Style Sauce and Cheese Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";
toppings.push_back("Grated Reggiano Cheese");
}
};

// 具体产品角色---纽约风味的比萨2
class NYStylePepperoniPizza : public Pizza
{
public:
NYStylePepperoniPizza()
{
name = "NY Style Pepperoni Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";
toppings.push_back("Grated Reggiano Cheese");
toppings.push_back("Sliced Pepperoni");
toppings.push_back("Garlic");
toppings.push_back("Onion");
toppings.push_back("Mushrooms");
toppings.push_back("Red Pepper");
}
};

// 具体产品角色---纽约风味的比萨3
class NYStyleVeggiePizza : public Pizza
{
public:
NYStyleVeggiePizza()
{
name = "NY Style Veggie Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";
toppings.push_back("Grated Reggiano Cheese");
toppings.push_back("Garlic");
toppings.push_back("Onion");
toppings.push_back("Mushrooms");
toppings.push_back("Red Pepper");
}
};

// 具体产品角色---纽约风味的比萨4
class NYStyleClamPizza : public Pizza
{
public:
NYStyleClamPizza()
{
name = "NY Style Clam Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";
toppings.push_back("Grated Reggiano Cheese");
toppings.push_back("Fresh Clams from Long Island Sound");
}
};

// 抽象工厂角色:工厂抽象类
class PizzaStore
{
public:
PizzaStore(){}
virtual ~PizzaStore(){}

// 这个函数接口是工厂方法,由子类实现,将创建对象推迟到子类
virtual Pizza* createPizza(string item) = 0;

Pizza* orderPizza(string type)
{
Pizza* pizza = createPizza(type);
cout << "--- Making a " << pizza->getName() << " ---" << endl;
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box();
return pizza;
}
};

// 具体工厂角色1:芝加哥的工厂
class ChicagoPizzaStore : public PizzaStore
{
public:
Pizza* createPizza(string item);
};

// 具体工厂角色2:纽约的工厂
class NYPizzaStore : public PizzaStore
{
public:
Pizza* createPizza(string item);
};

#endif


#include "FactoryMethodPattern.h"

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

void Pizza::prepare()
{
cout << "Preparing " << name << endl;
cout << "Tossing dough..." << endl;
cout << "Adding sauce..." << endl;
cout << "Adding toppings: " << endl;
for (size_t i = 0; i < toppings.size(); i++)
{
cout << "   " + toppings.at(i) << endl;
}
}

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()
{
// 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;
}

// 具体产品角色---芝加哥风味的比萨1
void ChicagoStyleClamPizza::cut()
{
cout << "Cutting the pizza into square slices" << endl;
}

// 具体产品角色---芝加哥风味的比萨2
void ChicagoStyleCheesePizza::cut()
{
cout << "Cutting the pizza into square slices" << endl;
}

// 具体产品角色---芝加哥风味的比萨3
void ChicagoStylePepperoniPizza::cut()
{
cout << "Cutting the pizza into square slices" << endl;
}

// 具体产品角色---芝加哥风味的比萨4
void ChicagoStyleVeggiePizza::cut()
{
cout << "Cutting the pizza into square slices" << endl;
}

// 具体工厂角色1:芝加哥的工厂
Pizza* ChicagoPizzaStore::createPizza(string item)
{
if (!item.compare("cheese"))
{
return new ChicagoStyleCheesePizza();
}
else if (!item.compare("veggie"))
{
return new ChicagoStyleVeggiePizza();
}
else if (!item.compare("clam"))
{
return new ChicagoStyleClamPizza();
}
else if (!item.compare("pepperoni"))
{
return new ChicagoStylePepperoniPizza();
}
else
{
return NULL;
}
}

// 具体工厂角色2:纽约的工厂
Pizza* NYPizzaStore::createPizza(string item)
{
if (!item.compare("cheese"))
{
return new NYStyleCheesePizza();
}
else if (!item.compare("veggie"))
{
return new NYStyleVeggiePizza();
}
else if (!item.compare("clam"))
{
return new NYStyleClamPizza();
}
else if (!item.compare("pepperoni"))
{
return new NYStylePepperoniPizza();
}
else
{
return NULL;
}
}


#include "FactoryMethodPattern.h"

void main()
{
PizzaStore* nyStore = new NYPizzaStore();
PizzaStore* chicagoStore = new ChicagoPizzaStore();

cout << "------------------------------------------------" << endl;
Pizza* pizza = nyStore->orderPizza("cheese");
cout << "Ethan ordered a " << pizza->getName() << endl;
delete pizza;

cout << "------------------------------------------------" << endl;
pizza = chicagoStore->orderPizza("cheese");
cout << "Joel ordered a " << pizza->getName() << endl;
delete pizza;

cout << "------------------------------------------------" << endl;
pizza = nyStore->orderPizza("clam");
cout << "Ethan ordered a " << pizza->getName() << endl;
delete pizza;

cout << "------------------------------------------------" << endl;
pizza = chicagoStore->orderPizza("clam");
cout << "Joel ordered a " << pizza->getName() << endl;
delete pizza;

cout << "------------------------------------------------" << endl;
pizza = nyStore->orderPizza("pepperoni");
cout << "Ethan ordered a " << pizza->getName() << endl;
delete pizza;

cout << "------------------------------------------------" << endl;
pizza = chicagoStore->orderPizza("pepperoni");
cout << "Joel ordered a " << pizza->getName() << endl;
delete pizza;

cout << "------------------------------------------------" << endl;
pizza = nyStore->orderPizza("veggie");
cout << "Ethan ordered a " << pizza->getName() << endl;
delete pizza;

cout << "------------------------------------------------" << endl;
pizza = chicagoStore->orderPizza("veggie");
cout << "Joel ordered a " << pizza->getName() << endl;
delete pizza;
pizza = NULL;

cout << "------------------------------------------------" << endl;
}
  
    该例的运行结果如图1所示,由于输出较多,所以只有前面的输出部分,后面的大家可以自行运行查看。



图1 部分执行结果

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



图2 UML类图

    从图2中可以看出,在工厂方法中必备的角色分别对应于:

(1)抽象产品角色是:Pizza类;
(2)具体产品角色是:后缀为Pizza的8个类(图2中指向Pizza类);
(3)抽象工厂角色是:PizzaStore类,它是抽象类,其中有一个抽象函数即createPizza()函数,这个函数留给子类实现,从而实现了所谓的将实际创建对象的确定留给子类决定;
(4)具体工厂角色是:ChicagoPizzaStore类和NYPizzaStore类,这两个类都各自实现了自己的createPizza()函数,从而实现了不同工厂方法。

    上面的例子是一个比萨店的订购系统,和上一篇讲的简单工厂模式是同样的思路,不过实现方法不一样,这里加入了新的比萨店,更为复杂一些,所以可以看出,简单工厂模式主要用于较为简单的对象创建中,当对象较多时,可以采用工厂方法模式,当然,下一篇马上就会讲到抽象工厂模式,在此之前大家先弄懂工厂方法模式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息