深入浅出《设计模式》之工厂模式(C++)

前言

模式介绍

在之前简单工厂模式中,我们介绍了简单工厂模式的缺陷是违背了开放-封闭原则。如果在面馆中添加了烤海参,那将会修改waiter工厂类。违背了类内封闭原则。

还以面馆为例,现在两种面,用一个服务员来卖就可以,如果这个服务员不干了,后面卖面的厨师需要兼职顶替服务员,但是厨师又不能离开灶台,就将模式改成了窗口排队式,一队海参炒面,另一队辣根汤面。每个窗口分别有一个厨师放饭,一个会做海参炒面,另一个会做辣根汤面。老板觉得这种模式挺好,万一来了一个会做烤海参的,就只需要开一个烤海参的窗口就好了,不需要重新要服务员学习,因为烤海参的就会卖。这就变成了工厂模式。

UML类图

这里涉及到2种类①我,客户端,排队买饭。②做饭厨师类,工厂类,为我生成饭。③菜品类,生成菜品类。具体关系如下UML类图:

A9wFLd.png

代码实例

下面是noodle类,是为工厂类使用的,继承他就可以扩展noodle类别:

#ifndef NOODLE_H
#define NOODLE_Hclass noodle
{
public:noodle() {}~noodle() {}virtual void eating() = 0;
};#endif // NOODLE_H

下面是海参炒面类,继承了noodle,实现eating方法,吃海参炒面:

#ifndef HAISHENNOODLE_H
#define HAISHENNOODLE_H#include "noodle.h"class haishennoodle : public noodle
{
public:haishennoodle();~haishennoodle();virtual void eating();
};#endif // HAISHENNOODLE_H
#include <iostream>
#include "haishennoodle.h"haishennoodle::haishennoodle()
{}haishennoodle::~haishennoodle()
{}void haishennoodle::eating()
{std::cout << "我是海参炒面,里面没有海参哦!!吃的时候注意!" << std::endl;
}

下面是辣根汤面,继承了noodle,实现eating方法,吃辣根汤面:

#ifndef LAGENNOODLE_H
#define LAGENNOODLE_H#include "noodle.h"class lagennoodle : public noodle
{
public:lagennoodle();~lagennoodle();virtual void eating();
};#endif // LAGENNOODLE_H
#include <iostream>
#include "lagennoodle.h"lagennoodle::lagennoodle()
{}lagennoodle::~lagennoodle()
{}void lagennoodle::eating()
{std::cout << "我是辣根汤面,吃完呛的哼啊!!!" << std::endl;
}

下面是waiter工厂的基类。所有工厂都继承这个类:

#ifndef WAITER_H
#define WAITER_Hclass noodle;
class waiter
{
public:waiter() {}~waiter() {}virtual noodle *createnoodle() = 0;
};#endif // WAITER_H

下面是海参厨师(工厂1),海参厨师只管做海参炒面,重写了createnoodle方法:

#ifndef HAISHEN_H
#define HAISHEN_H#include "waiter.h"class noodle;
class haishen : public waiter
{
public:haishen();~haishen();virtual noodle *createnoodle();
};#endif // HAISHEN_H
#include <iostream>
#include "haishen.h"
#include "haishennoodle.h"haishen::haishen()
{}haishen::~haishen()
{}noodle *haishen::createnoodle()
{std::cout << "面是我炒得,我的名字叫海参!!!" << std::endl;return new haishennoodle();
}

下面是辣根厨师(工厂1),辣根厨师只管做辣根汤面,重写了createnoodle方法:

#ifndef LAGEN_H
#define LAGEN_H#include "waiter.h"class lagen : public waiter
{
public:lagen();~lagen();virtual noodle *createnoodle();
};#endif // LAGEN_H
#include <iostream>
#include "lagen.h"
#include "lagennoodle.h"lagen::lagen()
{}lagen::~lagen()
{}noodle *lagen::createnoodle()
{std::cout << "吃辣根汤面,你不觉得呛得哼吗??" << std::endl;return new lagennoodle();
}

下面是客户端,客户端通过类别,使用相应的工厂类建立相应的实例:

#include <iostream>
#include <string.h>#include "haishen.h"
#include "lagen.h"
#include "noodle.h"using namespace std;char *product_list[] = {"haishen-noodle","lagen-noodle",NULL
};int main()
{char *p = NULL;char *pd = "haishen-noodle";int i = 0;waiter *w = NULL;noodle *n = NULL;for(p = product_list[i]; p != NULL; i++, p = product_list[i]) {if(strncmp(pd, p, strlen(pd)) == 0) {if(i == 0) {w = new haishen();} else if(i == 1) {w = new lagen();} else {cout << "对不起,请您排在队内!!!" << std::endl;break;}}}if(w) n = w->createnoodle();if(n) n->eating();if(w) {delete w; w = NULL;}if(n) {delete n; n = NULL;}return 0;
}

下面是CMakeList.txt文件,帮助生成Makefile:

cmake_minimum_required(VERSION 2.8)project(noodle-factory)
set(SRC_LIST main.cpp noodle.h waiter.h haishen.h haishen.cpp haishennoodle.h haishennoodle.cpplagennoodle.h lagennoodle.cpp lagen.h lagen.cpp)
add_executable(${PROJECT_NAME} ${SRC_LIST})

编译运行结果

代码下载链接是:https://github.com/erguangqiang/freesir_headfirst/blob/master/noodle-factory.tar.gz
使用cmake生成Makefile,并编译出可执行程序noodle。运行结果如下:

erguangqiang@elab$./noodle-factory
面是我炒得,我的名字叫海参!!!
我是海参炒面,里面没有海参哦!!吃的时候注意!

结束

工厂模式解决了简单工厂违背了的开放-封闭原则。虽然累的结构变的复杂了,但是对于扩展性得到了很大的提高。

转载于:https://www.cnblogs.com/freeman2012/p/11206166.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/349972.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

当心Spring缓慢的事务回调

TL; DR 如果您的应用程序无法获得新的数据库连接&#xff0c;则重新启动ActiveMQ代理可能会有所帮助。 有兴趣吗 性能问题 几个月前&#xff0c;我们经历了生产中断。 大家都很熟悉&#xff0c;许多请求都失败了&#xff1a; java.sql.SQLTransientConnectionException: Hika…

jmeter学习笔记(八-1)

Jmeter中有较多需要参数化测试的地方&#xff1a; 1.从一个用户登录的接口获取登录后的token值&#xff0c;取值后用于后续接口调用 2.获取用户浏览后的cookies信息&#xff0c;需要用到HTTP Cookie 管理器来为同一线程组提供通用的cookies信息 Jmeter中通过${}形式来取参数值 …

python 对象转dict_如何将python dict对象转换为java等效对象?

总是有jython。这里有一点来自this article&#xff0c;它提供了python/java的良好并排视图The Jython analogues to Javascollection classes are much moretightly integrated into the corelanguage, allowing for more concisedescriptions and useful functionality.For e…

NOIP模拟测试5「星际旅行·砍树·超级树」

星际旅行 0分 瞬间爆炸。 考试的时候觉得这个题怎么这么难&#xff0c; 打个dp&#xff0c;可以被儿子贡献&#xff0c;可以被父亲贡献&#xff0c;还有自环&#xff0c;叶子节点连边可以贡献&#xff0c;非叶子也可以贡献&#xff0c;自环可以跑一回&#xff0c;自环可以跑两回…

学java选i5还是i7_选笔记本电脑,到底CPU是要选i5还是i7

又到了一年毕业季&#xff0c;准备上大学的学生们肯定是摩拳擦掌&#xff0c;准备入手一台新的笔记本电脑。而我们在选购笔记本电脑的时候&#xff0c;经常会遇到不同的配置&#xff0c;比如说同一台笔记本电脑会有i5以及i7两个处理器可供选择&#xff0c;而价格往往相差一两千…

apache apollo_Apache Apollo REST API

apache apolloApache Apollo是新一代&#xff0c;高性能&#xff0c;多协议的消息传递代理&#xff0c;它是从头开始构建的&#xff0c;可以替代ActiveMQ5.x。 我过去曾在博客上发表过文章 &#xff08;第一部分已经与第二部分一起发布了&#xff09;。 Apollo的无阻塞异步体系…

Node 之 模块加载原理与加载方式

Node.js中的模块可以分为原生模块和文件模块&#xff0c;通过Node.js中可以通过require方法导入模块、exports方法导出模块。 1、require导入模块 对于原生模块&#xff08;比如说&#xff1a;http&#xff09;&#xff0c;只需要使用require&#xff08;‘http’&#xff09;导…

php excel 下拉菜单,使用 PHPExcel 遇到的一个问题:下拉列表的数据来源过长时,显示了别的正常的下拉列表的数据来源...

遇到的问题&#xff1a;我们还是先来看手册是怎么说的&#xff1a;It is important to remember that any string participating in an Excel formula is allowed to be maximum 255 characters (not bytes).当下拉列表的数据来源过长(more than 255 characters)时&#xff0c;…

有效的Java –创建和销毁对象

创建和销毁对象&#xff08;第2章&#xff09; 这是Joshua Blochs的《 有效的Java》第2章的简短摘要。我仅包括与自己相关的项目。 静态工厂&#xff08;项目1&#xff09; 静态工厂与构造函数的一些优点&#xff1a; 工厂方法的名称为构造函数添加了描述 他们可以返回预先构…

【洛谷P2743】【poj 1743】[USACO5.1]乐曲主题Musical Themes

题目 还是板子题 因为旋律会同时加减一个数&#xff0c;所以我们在差分数组上做就好了 注意因为差分了&#xff0c;跨越的个数要少一个 基数排序循环写反了&#xff0c;调了好久 qwq /* Date : 2019-07-19 10:17:22 Author : Adscn (adscnqq.com) Link : https://www.cn…

exec导入 php,PHP exec运行一个文件

我正在尝试最后3个小时告诉PHP运行一个简单的文件.我在本地主机中使用wamp服务器用于Windows(Windows 8)我尝试过使用exec()&#xff1a;echo exec(whoami);我得到了权威的回应.还测试了&#xff1a;if(function_exists(exec)) {echo "exec is enabled";}它可能有用吗…

远程连接Oracle 数据库连接报错ORA-12638身份检索失败

数据库版本&#xff1a;oracle11g 当使用navicate或者PLsql使用远程连接服务器的数据库的时候报错 RA-12638身份检索失败 因为是更换了个新电脑出现这种问题了&#xff0c;所以可以排除时服务器数据库的问题&#xff0c;问题应该出现在oracle的客户端上面&#xff1b; 通过修改…

java生成顺丰电子面单,顺丰拼多多电子面单设置教程

100%使用使用拼多多电子面单&#xff0c;无需解密&#xff0c;即可打单发货&#xff0c;让打单更加流畅&#xff0c;减少出错&#xff01;不少商家有疑问&#xff0c;顺丰是月结的合作模式&#xff0c;不用充快递单号&#xff0c;是不是不支持拼多多电子面单呢&#xff1f;当然…

list.action.php,doAction.php里代码可以这样写,大大减少了重复的代码

//接收页面$mysqlinew Mysqli(localhost,root,root,test);if($mysqli->connect_errno){die(Connect Error:.$mysqli->connect_error);}$mysqli->set_charset(utf8);$username$_POST[username];$username$mysqli->escape_string($username);$password$_POST[passwor…

[Jobdu] 题目1530:最长不重复子串

题目描述&#xff1a;最长不重复子串就是从一个字符串中找到一个连续子串&#xff0c;该子串中任何两个字符都不能相同&#xff0c;且该子串的长度是最大的。 输入&#xff1a;输入包含多个测试用例&#xff0c;每组测试用例输入一行由小写英文字符a,b,c...x,y,z组成的字符串&a…

Spring Boot,@ EnableWebMvc和常见用例

事实证明&#xff0c;Spring Boot与标准Spring MVC EnableWebMvc不能很好地融合EnableWebMvc 。 添加注释时发生的事情是禁用了Spring Boot自动配置。 不好的部分&#xff08;浪费了我几个小时&#xff09;是&#xff0c;在任何指南中&#xff0c;您都找不到明确指出的内容。 …

php redirect with post,PHP – redirect并通过POST发送数据

你不能用PHP做这个。正如其他人所说&#xff0c;你可以使用cURL – 但是然后PHP代码成为客户端&#xff0c;而不是浏览器。如果您必须使用POST&#xff0c;那么唯一的方法就是使用PHP生成填充表单&#xff0c;并使用window.onload挂钩来调用javascript来提交表单。C。这里是解决…

php static方法的作用是什么,php static方法指的是什么

php static方法指的是用php中static关键字来定义静态方法和属性&#xff0c;static也可用于定义静态变量以及后期静态绑定&#xff0c;其使用语法如“public static $my_static foo;”。推荐&#xff1a;《PHP教程》Static(静态)关键字本页说明了用 static 关键字来定义静态方…

您好您拨打电话已停机_您好GroovyFX

您好您拨打电话已停机GroovyFX汇集了我最喜欢的两件事&#xff1a; Groovy和JavaFX 。 GroovyFX项目主页面将GroovyFX描述为“ [为JavaFX 2.0提供Groovy绑定”。 该页面上进一步描述了GroovyFX&#xff1a; GroovyFX是一种API&#xff0c;它使在Groovy中使用JavaFX变得更加简…

js中写java集合代码,JS实现JAVA的List功能

本次的文章给大家分享了关于JS实现JAVA的List功能的代码&#xff0c;有兴趣的朋友可以看一下function List(){var list new Array();/* 添加元素 */this.add function(obj){list[list.length] obj;}/* 根据下标获得元素 */this.get function(index){return list[index];}/*…