模式定义:

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。

工厂方法让类把实例化推迟到子类。

模式结构:


Creator是一个类,它实现了全部操纵产品的方法,但不实现工厂方法。

Creator的全部子类都必须实现工厂方法(factoryMethod()),以实际制造出产品。

全部的产品必须实现Product基类。这样一来使用这些产品的类就能够引用这个基类,而不是派生类。

举例:

披萨店希望可以开一些加盟店。

经营者希望确保加盟店运营的质量,所以希望这些店都使用能经过实践考研的代码。问题在于每家加盟店都可能想要提供不同风味的披萨(例如说纽约。芝加哥,加州)。这收到了开店地点及该地区披萨口味的影响。

解决的方法:让每一个区域风味的披萨工厂继承基类披萨工厂使披萨工厂的订单系统不变。然后创建自己风味的披萨。这样真正选购披萨类型,使用详细的披萨工厂决定的。

类图设计:


编程实现及运行结果:

#include <iostream>
#include <string>
#include <list>
using namespace std;

首先创建Pizza类

class Pizza
{
public:
Pizza(string nam, string doug, string sauc)
{
name = nam;
dough = doug;
sauce = sauc;
}
void addTops(string tops)
{
toppings.push_back(tops);
} void prepare()
{
cout << "Preparing " << name << endl;
cout << "Tossing dough" << endl;
cout << "Adding sauce" << endl;
cout << "Adding toppings" << endl;
list<string>::iterator iter = toppings.begin();
for(; iter!=toppings.end(); ++iter)
{
cout << " "<< *iter;
}
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 offical PizzaStore box" << endl;
} string getName()
{
return name;
} private:
string name;
string dough;
string sauce;
list<string> toppings;
};

然后创建纽约cheese风格的pizza类和纽约clam风格的pizza类

class NYStyleCheesePizza : public Pizza
{
public:
NYStyleCheesePizza():Pizza("NY Style Sauce and Cheese Pizza",
"Thin Crust Dough", "Marinara Sauce")
{
addTops("Grated Reggiano Cheese");
}
};
class NYStyleClamPizza : public Pizza
{
public:
NYStyleClamPizza():Pizza("NY Style Sauce and Clam Pizza",
"Thin Crust Dough", "Marinara Sauce")
{
addTops("Grated Clam");
}
};

创建基类工厂

class PizzaStore
{
public:
virtual ~PizzaStore(){} Pizza* oderPizza(string type)
{
Pizza* pizza = createPizza(type);
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box(); return pizza;
} virtual Pizza* createPizza(string type){return NULL;} };

创建详细类工厂(纽约pizza工厂)

class NYPizzaStore : public PizzaStore
{
public:
Pizza* createPizza(string item)
{
if(item == "cheese")
{
return new NYStyleCheesePizza();
}
else if(item == "clam")
{
return new NYStyleClamPizza();
}
else
return NULL;
}
};
//...创建其它地区工厂...

客户代码:

int main()
{
PizzaStore* nyStore = new NYPizzaStore();
Pizza* pizza = nyStore->oderPizza("cheese");
cout << "Ethan ordered a "<< pizza->getName() << endl; return 0;
}

运行结果:

PreparingNY Style Sauce and Cheese Pizza

Tossingdough

Addingsauce

Addingtoppings

        Grated Reggiano Cheese

Bakefor 25 minutes at 350

Cuttingthe pizza into diagonal slices

Placepizza in offical PizzaStore box

Ethanordered a NY Style Sauce and Cheese Pizza

请按随意键继续. . .

设计原则的应用:

设计原则6:依赖倒置原则(Dependency Inversion Priciple):要依赖抽象,不要依赖详细类。

设计原则4:工厂方法用来处理对象的创建,并将这种行为封装在子类中。这样,客户中关于基类的代码和子类对象对象创建代码解耦了。

參考Head First设计模式

设计模式C++实现——工厂方法模式的更多相关文章

  1. 大话设计模式C++版——工厂方法模式

    工厂方法模式是以简单工厂模式为基础的,如果未了解简单工厂模式的同学可先浏览<大话设计模式C++版——简单工厂模式>.在简单工厂模式中,提到过简单工厂模式的缺陷,即违背了开发—封闭原则,其主 ...

  2. IOS设计模式浅析之工厂方法模式(Factory Method)

    概述 在软件系统中,经常面临着“某个对象”的创建工作,由于需求的变化,这个对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定的接口. 如何隔离出这个易变对象的变化,使得系统中“其它依赖该对象的对 ...

  3. [设计模式]<<设计模式之禅>>工厂方法模式

    1 女娲造人的故事 东汉<风俗通>记录了一则神话故事:“开天辟地,未有人民,女娲搏黄土做人”,讲述的内容就是大家非常熟悉的女娲造人的故事.开天辟地之初,大地上并没有生物,只有苍茫大地,纯粹 ...

  4. java设计模式-----2、工厂方法模式

    再看工厂方法模式之前先看看简单工厂模式 工厂方法模式(FACTORY METHOD)同样属于一种常用的对象创建型设计模式,又称为多态工厂模式,此模式的核心精神是封装类中不变的部分,提取其中个性化善变的 ...

  5. C#设计模式之二工厂方法模式(Factory Method Pattern)【创建型】

    一.引言 在上一篇文章中我们讲解了过渡的一种模式叫做[简单工厂],也有叫[静态工厂]的,通过对简单工厂模式得了解,我们也发现了它的缺点,就是随着需求的变化我们要不停地修改工厂里面的方法的代码,需求变化 ...

  6. 大话设计模式Python实现-工厂方法模式

    工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延时到其子类. #!/usr/bin/env python ...

  7. 【C#设计模式3】工厂方法模式

    一.引言 在简单工厂模式中讲到简单工厂模式的缺点,有一点是——简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,然而本专题介绍的工厂方法模式可以 ...

  8. 重学 Java 设计模式:实战工厂方法模式

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!

  9. 《Head First 设计模式》:工厂方法模式

    正文 一.定义 工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个.工厂方法让类把实例化推迟到子类. PS:在设计模式中,"实现一个接口"泛指实现某个超类型(可 ...

随机推荐

  1. PAT Basic 1049

    1049 数列的片段和 给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段.例如,给定数列 { 0.1, 0.2, 0.3, 0.4 },我们有 (0.1) (0.1, 0.2) (0.1 ...

  2. Experiments done

    喷重金属 换重金属溶液 荧光光合 备注 ASD 备注 高光谱 备注 泡EDTA 备注 电镜 备注 2018.12.19(day1) 2018.12.19(day1) 2018.12.18晚(day0) ...

  3. go的相关用法

    1. have gone to和have been to的区别 have gone to和have been to的区别如下: 1.have gone to,第三人称时用 has gone to ha ...

  4. mac下secureCRT 客户端 $redis-cli回车后没有反应的解决办法

    启动redis server后,SecureCRT进入redis-cli,输入不断在后面追加IP:Port显示设置当前的Session Options-->Terminal-->Emula ...

  5. python中判断字符串是否为中文

    判断字符串是否在中文编码范围内 for c in s:        if not ('\u4e00' <= c <= '\u9fa5'):            return False ...

  6. 电子邮件中的to、cc、bcc

    电子邮件中的to.cc(carbon copy)和bcc(blind carbon copy),分别是收件人.抄送.密送 to 收件人 你想要给其发邮件的人 cc 抄送人 cc和to是一样的,但是cc ...

  7. mysql数据库修改字段类型

    修改字段类型: alter table 表名 modify column 字段名字 decimal(18, 4) ;

  8. Codeforces Round #417 (Div. 2) 花式被虐

    A. Sagheer and Crossroads time limit per test 1 second memory limit per test 256 megabytes input sta ...

  9. TOJ 4815: 关押罪犯

    4815: 关押罪犯 Time Limit(Common/Java):10004MS/12000MS     Memory Limit:65536KByte Total Submit: 2       ...

  10. RAC+单节点搭建DG

    primary RAC to single standby 参考文献:RAC+单实例DATAGUARD 配置   http://blog.csdn.net/miyatang/article/detai ...