深入浅出《设计模式》之工厂模式(C++)
前言
模式介绍
在之前简单工厂模式中,我们介绍了简单工厂模式的缺陷是违背了开放-封闭原则。如果在面馆中添加了烤海参,那将会修改waiter工厂类。违背了类内封闭原则。
还以面馆为例,现在两种面,用一个服务员来卖就可以,如果这个服务员不干了,后面卖面的厨师需要兼职顶替服务员,但是厨师又不能离开灶台,就将模式改成了窗口排队式,一队海参炒面,另一队辣根汤面。每个窗口分别有一个厨师放饭,一个会做海参炒面,另一个会做辣根汤面。老板觉得这种模式挺好,万一来了一个会做烤海参的,就只需要开一个烤海参的窗口就好了,不需要重新要服务员学习,因为烤海参的就会卖。这就变成了工厂模式。
UML类图
这里涉及到2种类①我,客户端,排队买饭。②做饭厨师类,工厂类,为我生成饭。③菜品类,生成菜品类。具体关系如下UML类图:
代码实例
下面是noodle类,是为工厂类使用的,继承他就可以扩展noodle类别:
#ifndef NOODLE_H
#define NOODLE_H
class 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_H
class 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.cpp
lagennoodle.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
面是我炒得,我的名字叫海参!!!
我是海参炒面,里面没有海参哦!!吃的时候注意!
结束
工厂模式解决了简单工厂违背了的开放-封闭原则。虽然累的结构变的复杂了,但是对于扩展性得到了很大的提高。
深入浅出《设计模式》之工厂模式(C++)的更多相关文章
- 深入浅出设计模式——简单工厂模式(Simple Factory)
介绍简单工厂模式不能说是一个设计模式,说它是一种编程习惯可能更恰当些.因为它至少不是Gof23种设计模式之一.但它在实际的编程中经常被用到,而且思想也非常简单,可以说是工厂方法模式的一个引导,所以我想 ...
- 深入浅出设计模式——抽象工厂模式(Abstract Factory)
模式动机在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法.但是有时候我们需要一个工厂可 ...
- 设计模式——抽象工厂模式及java实现
设计模式--抽象工厂模式及java实现 设计模式在大型软件工程中很重要,软件工程中采用了优秀的设计模式有利于代码维护,方便日后更改和添加功能. 设计模式有很多,而且也随着时间在不断增多,其中最著名的是 ...
- 5. 星际争霸之php设计模式--抽象工厂模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- 3. 星际争霸之php设计模式--简单工厂模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- iOS 设计模式之工厂模式
iOS 设计模式之工厂模式 分类: 设计模式2014-02-10 18:05 11020人阅读 评论(2) 收藏 举报 ios设计模式 工厂模式我的理解是:他就是为了创建对象的 创建对象的时候,我们一 ...
- 设计模式之工厂模式(Factory)
设计模式的工厂模式一共有三种:简单工厂模式,工厂模式,抽象工厂模式 简单工厂模式原理:只有一个工厂类,通过传参的形式确定所创建的产品对象种类 代码如下: #include <stdio.h> ...
- php设计模式:工厂模式
php设计模式:工厂模式 意图: 定义一个用于创建对象的接口,让子类决定实例化哪一个类. 工厂模式实现: 工厂模式中任何创建对象的工厂类都要实现这个接口,实现接口的方法体中都要实现接口中的方法,它声明 ...
- 浅析JAVA设计模式之工厂模式(一)
1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...
- java 设计模式之工厂模式与反射的结合
工厂模式: /** * @author Rollen-Holt 设计模式之 工厂模式 */ interface fruit{ public abstract void eat(); } ...
随机推荐
- 被公司的垃圾XG人事系统吓尿了
OA要尝试设置单点登录,拿现有的HR系统尝试,结果不知道HR系统的加密方式和验证地址,于是乎找HR厂商——厦门XG软件实施人员.结果那个技术人员支支吾吾不肯给我,搞得非常的烦. 真奇怪了,不开源的软件 ...
- 仅用StoryBoard布局实现按钮的均匀分布
今天在做登录界面时设计的需求是,登录和取消按钮左右对称均匀分布,按钮大小不变如图 屏幕宽度变化时按钮宽度不变,三个间距相等并且随屏幕变化而变化,简单的说就是按钮均匀分布,在网上查了一些资料,弄得比较乱 ...
- JSON解析(序列化和反序列化)
JSON的序列化,代码示例: NSDictionary *dic = @{}; if (![NSJSONSerialization isValidJSONObject:dic]) { NSLog(@& ...
- [b0037] python 归纳 (二二)_多进程数据共享和同步_管道Pipe
# -*- coding: utf-8 -*- """ 多进程数据共享 管道Pipe 逻辑: 2个进程,各自发送数据到管道,对方从管道中取到数据 总结: 1.只适合两个进 ...
- Lnmp架构部署动态网站环境.2019-7-3-1.4
安装wiki开源产品 一.创建数据库 [root@Lnmp bbs]# mysql -uroot -p123456 mysql> create database wiki; #创建wiki数据库 ...
- spark Streaming与kafka的集成消费
Spark 2.3.3 Kafka 2.11-1.0.2 Java jdk1.8.0_191 Hbase 1.2.11 from pyspark impo ...
- 利用Git生成本机SSH Key并添加到GitHub中
本地仓库和github之间是通过SSH加密传输的,所以需要先到github中添加你本机的SSH Key 进行认证. 1.在桌面打开git命令窗口 2.输入“ssh-keygen -t rsa -C ...
- 冒泡排序法(C语言)
冒泡排序(Bubble Sort)一种计算机科学领域的较简单的排序算法.它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小.首字母从从Z到A)错误就把他们交换过来.走访元素的工 ...
- 【2019.8.8 慈溪模拟赛 T2】query(query)(分治+分类讨论)
分治 首先,我们考虑分治处理此问题. 每次处理区间\([l,r]\)时,我们先处理完\([l,mid]\)和\([mid+1,r]\)两个区间的答案,然后我们再考虑计算左区间与右区间之间的答案. 处理 ...
- A1029 Median (25 分)
一.技术总结 最开始的想法是直接用一个vector容器,装下所有的元素,然后再使用sort()函数排序一下,再取出中值,岂不完美可是失败了,不知道是容器问题还是什么问题,就是编译没有报错,最后总是感觉 ...