当前位置: 首页 > 编程日记 > 正文

设计模式之简单工厂模式

一、概述

工厂模式具体包括了简单工厂、工厂方法、抽象工厂,它们是按照从简单到复杂的顺序排列的,属于设计模式中的创建型,其中简单工厂并不属于GOF的23中模式。
  但是它是理解其它的工厂模式的一个很好的基础,所以很多人在讲述设计模式的时候会提到简单工厂模式。
  创建型模式关注的是对象的创建,创建型模式将创建对象的过程进行了抽象,也可以理解为将创建对象的过程进行了封装,作为客户程序仅仅需要去使用对象,而不再关心创建对象过程中的逻辑。

  优点:
  1)解决了代码中大量的new的问题,把new对象的操作集中封装到工厂类里面,这样一来,用工厂方法在一个类的内部创建对象通常比直接创建对象更灵活
  缺点:
  1)由于是简单的封装,所以此模式下对修改不封闭,新增产品时需要修改工厂类,违犯了开闭法则(OCP)。
        因为如果直接在工厂类的内部生产(new)所有的产品,当新增产品时,要去修改工厂类,封装性不好。 
  举例说明:
  简单工厂就是把某一类的产品做了规划,使其形成一个产品集合。但这些产品类不直接对外开放,而是通过它们的基类接口供外界调用,
  这就如同一个鞋厂,我们提货当然不能直接到生产部提货的, 你要知道生产部流水线很多的,他们只知道自己线上的型号,其它线上的型号可是一问三不知,何况作为一个外来人员,你要申请才能去参观哦。
  所以你就不要折腾了,这个鞋厂已经安排了销售部负责对外供货。如果我们需要什么型号的皮鞋,直接找销售部,销售部会帮你做好一切安排。
  现在很多代码都是没用使用工厂类,而是直接调用Prodcut类直接使用产品的,这就造成new来new去漫天飞,现在有了简单工厂模式,规划好产品,管理好产品,一切都在向良性方向发展。
 
  简而言之:  
  简单工厂两个类簇:一个类簇是Product,重在实现产品;一个类簇是Factory,重在是创建及管理产品。原则上,外界对产品的操作只能通过Factory,而不能直接对Product,这样保护了Product的秘密性。
 
  Product类负责完成各种各样的产品,对外面只提供有限的接口;它有2层结构:产品虚基类-产品子类
  Factory类负责创建产品,它有1层结构:简单工厂类

二,类图:

三,代码:

SimpleFactory.h

#pragma once//工厂类依赖于产品类,因为没有产品的工厂不能称之为工厂,所以有://工厂类---(调用)--->产品类
#include "IProduct.h" //下面的头文件其实应该放到cpp文件里面,之所以放在这里是为了更好诠释简单工厂模式(将它们一齐集中到h文件说明)
#include "ConcreteProductA.h" 
#include "ConcreteProductB.h"//工厂类:外层返回产品基类,内层生产(创建,new)具体的产品。
//这就像是工厂向外界供货一样,客户需要什么产品,一个电话打到生产部,让生产部直接拿产品过来。即:一步(new)成型,并不会关注产品的制作过程。
class CSimpleFactory
{
public:CSimpleFactory() {};~CSimpleFactory() {};public:IProduct * CreateProduct(int nProductType);IProduct *CreateProductA();IProduct *CreateProductB();};

SimpleFactory.cpp

#include"SimpleFactory.h"IProduct *CSimpleFactory::CreateProduct(int nProductType)
{IProduct *ptr = 0;switch (nProductType){case 0:ptr = new CConcreteProductA();break;case 1:ptr = new CConcreteProductB();break;default:ptr = new CConcreteProductA();}return ptr;}IProduct *CSimpleFactory::CreateProductA()
{cout<<__FUNCTION__<<endl;return new CConcreteProductA();
}IProduct *CSimpleFactory::CreateProductB()
{cout<<__FUNCTION__<<endl;return new CConcreteProductB();
}

IProduct.h

#pragma once#include <stdio.h>
#include <iostream>
using namespace std;//这是一个产品虚基类:它的任务就是用来定型(抽象)所需求产品,抽象出它们的公共属性,然后让它的派生类一门心思地去完成自身的功能。
//所以它并不依赖于任何业务相关的头文件,但有可能会依赖系统头文件,比如你使用了string,必须要包含string头文件
//这个产品基类之所以存在是因为我们要为我们生产的产品抽象出了它们的公共属性,而这个公共属性是对外开放,供外部(比如说客户端程序)调用的。
//外部调用时将以多态性进行操作,不会接触到产品内部的细节,这样就保证的产品的封闭性。class IProduct
{
protected:IProduct();public:virtual ~IProduct();public:virtual void Function() = 0;
};

IProduct.cpp

#include "IProduct.h"IProduct::IProduct(void)
{}IProduct::~IProduct(void)
{}

ConcreteProductA.h

#pragma once
#include "IProduct.h" //CConcreteProductA(派生类) ----|> IProduct(基类)//实现产品的具体细节:基于产品功能需求(基类接口),具体化出功能A产品
class CConcreteProductA :public IProduct
{
public:CConcreteProductA();virtual ~CConcreteProductA();virtual void Function();
};

ConcreteProductA.cpp

#include "ConcreteProductA.h"
CConcreteProductA::CConcreteProductA(void)  
{cout<<__FUNCTION__<<endl;
}CConcreteProductA::~CConcreteProductA(void) 
{cout<<__FUNCTION__<<endl;
}void CConcreteProductA::Function() 
{cout<<__FUNCTION__<<endl;
}

ConcreteProductB.h

#pragma once
#include "IProduct.h" //CConcreteProductA(派生类) ----|> CProduct(基类)//实现产品的具体细节:基于产品功能需求(基类接口),具体化出功能B产品
class CConcreteProductB :public IProduct
{
public:CConcreteProductB(void);virtual ~CConcreteProductB(void);virtual void Function();
};

ConcreteProductB.cpp

#include "ConcreteProductB.h"CConcreteProductB::CConcreteProductB(void)  
{cout<<__FUNCTION__<<endl;
}CConcreteProductB::~CConcreteProductB(void) 
{cout<<__FUNCTION__<<endl;
}void CConcreteProductB::Function() 
{cout<<__FUNCTION__<<endl;
}

main.cpp

#include "SimpleFactory.h"
#include <stdio.h>int main()
{CSimpleFactory fac;IProduct *pProduct = fac.CreateProductA();pProduct->Function();delete pProduct;pProduct = NULL;pProduct = fac.CreateProductB();pProduct->Function();delete pProduct;pProduct = NULL;return 0;
}

四,运行结果:

CSimpleFactory::CreateProductA
CConcreteProductA::CConcreteProductA
CConcreteProductA::Function
CConcreteProductA::~CConcreteProductA
CSimpleFactory::CreateProductB
CConcreteProductB::CConcreteProductB
CConcreteProductB::Function
CConcreteProductB::~CConcreteProductB
请按任意键继续. . .

转载于:https://www.cnblogs.com/jacklikedogs/p/3807648.html

相关文章:

zendserver的版本是怎么回事?免费版哪里去了?

zend server 的版本&#xff0c;官网上说是四个版本&#xff0c;免费版、小企业版、专业版、企业版。 但下载只有一个版本。在下载的页面中大大的free download 很是显眼。安装完成之后显示为企业版。使用几天之后&#xff0c;显示你的许可即将到期。 输入密码&#xff0c;登录…

sql-case when 条件1 then 取值1 when 条件2 then 取值2 else 取值3 end

遇到 XXX情况 就 XXX 遇不到就 XXX 结束case when …… then …… else …… end 例如一个3条件取值的字段&#xff1a; case when 条件1 then 取值1 when 条件2 then 取值2 else 取值3 end when后接条件语句&#xff0c;then后为字段取值&#xff08;数值或字符串等都可以&…

二叉树:二叉搜索树的创建和插入

二叉搜索树又名二叉排序树。 大概简略的思维导图如下&#xff0c;方便记忆特性 基本二叉搜索树创建过程如下 /*数据结构如下*/ typedef struct tree {int data;struct tree *left NULL;struct tree *right NULL; }Tree,*TreeNode;/*Node 为二叉树根节点&#xff0c;insert…

ie7和ie8 select使用jquery clone不兼容处理

本文解决方案基于http://blog.csdn.net/zzx3q/article/details/8017794 在ie7和ie8下&#xff0c;用jquery clone复制一个select&#xff0c;复制的select是本体的select初始化时的一个副本&#xff0c;无法复制目前本体select选择。 解决方案&#xff1a; <!DOCTYPE html&g…

c语言中floox的头文件,PC-1211袖珍计算机在合成氨厂生产中的应用 第五讲 循环语句(FOR-NEXT语句)...

PC-1211袖珍计算机在合成氨厂生产中的应用 第五讲 循环语句(FOR-NEXT语句)在化工生产中为了分析两个或两个以上参数对生产的影响往往需要进行某些有规律的重复计算。这些计算在程序中可以用赋值语句或条件语句来实现,但从下面的介绍可以看出,这时若采用循(本文共7页)阅读全文&g…

C#Winform+WindowsAPI做个剪贴板无缝自动保存器(视频截图利器)

C#WinformWindowsAPI做个剪贴板无缝自动保存器&#xff08;视频截图利器&#xff09; (本文最新代码已上传到GitHub&#xff0c;地址在&#xff08;https://github.com/bitzhuwei/ClipboardImageSaver&#xff09;) 利用C#和Window API做了个自动保存剪贴板内的图片的工具&…

Kafka配置SASL/PLAIN认证

1、安装zk&#xff0c;kafka 2、配置server.properties security.inter.broker.protocolSASL_PLAINTEXT sasl.mechanism.inter.broker.protocolPLAIN sasl.enabled.mechanismsPLAIN listenersSASL_PLAINTEXT://0.0.0.0:9092 advertised.listenersSASL_PLAINTEXT://host:9092 3…

二叉树:二叉搜索树的编码和解码

二叉搜索树的编码和解码描述&#xff1a; 编码&#xff1a;即将一个二叉搜索树编码&#xff0c;节点数值转换为字符串 解码&#xff1a;即将一个字符串解码&#xff0c;数值转换为对应的二叉搜索树的节点 过程导图如下&#xff1a; 针对性编码实现如下: /*数字转字符串*/ vo…

springmvc3.2+spring+hibernate4全注解方式整合(一)

<?xml version"1.0" encoding"UTF-8"?> <web-app xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xmlns"http://java.sun.com/xml/ns/javaee" xmlns:web"http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&…

c 应用程序多语言版本,c – 在win32 API应用程序中实现全球化/多语言功能

Windows上多语言应用程序的基础是使用“资源”.资源是附加在可执行文件末尾的块,它只包含数据,并以非常特定的方式格式化,以便Windows能够解释这些数据.在资源中,您可以找到对话框,字符串表以及版本信息(在资源管理器中文件的属性对话框中显示的信息).您可以通过在Visual C中打…

整数展示分数和整形数的四则运算

文章结束给大家来个序程员笑话&#xff1a;[M] /* * Copyright (c) 2013, 烟台大学计算机学院 * All rights reserved. * 文件名称&#xff1a;test.cpp * 作者&#xff1a;邱学伟 * 成完日期&#xff1a;2013 年 5 月 4 日 * 版本号&#xff1a;v1.0 * 输入描述&#xff1a;无…

二叉树:二叉搜索树实现 逆序数问题

关于逆序数的问题描述如下&#xff1a; 已知数组nums&#xff0c;求新数组count&#xff0c;count[i]代表了在nums[i]右侧且比 nums[i]小的元素个数。 例如: nums [5, 2, 6, 1], count [2, 1, 1, 0]; nums [6, 6, 6, 1, 1, 1], count [3, 3, 3, 0, 0, 0]; nums [5, -7, 9…

C语言文件实验要求,实验教学的目的和要求.doc

实验教学的目的和要求实验教学的目的和要求&#xff1a;通过实验&#xff0c;让学生全面掌握高级语言程序设计的思想与方法&#xff0c;掌握C语言的特点&#xff0c;C语言的语法规则&#xff0c;C语言的数据类型、表达式及控制流程&#xff1b;通过编程&#xff0c;提高程序设计…

这些工作的日子

已经毕业10个月了&#xff0c;工作了9个月&#xff0c;想说我是个刚毕业的大学僧&#xff0c;没有遇到什么社会上的勾心斗角&#xff0c;没有遇到天大的难题&#xff0c;没有看到那种大起大落的景象&#xff0c;一切还是那样平平淡淡的&#xff0c;当看见附近大学的大学僧的时候…

python基础类型

range&#xff1a;生成指定范围内的数字&#xff0c;只在python2中使用&#xff0c;python3中没有此用法 例&#xff1a;生成0-30内的偶数 转载于:https://www.cnblogs.com/gaoyuxia/p/10239421.html

linux系统目录树/内核源码目录树

关于系统目录树和源码目录树的结构图如下 内核版本: centos 7.0 升级内核之后 3.10.0-957-5.1.e17

顺时针打印二维数组C语言递归,按顺时针打印矩阵

存在二种解题思路: 一种是递归解法,一种是层层递进解法图解递归解法如图所示, 一个5*5的矩阵先打印最外层的圈, 然后剩余最里层3*3的矩阵, 如图.将3*3的矩阵继续打印最外层,思路与打印最外层思路一样,我们就可以考虑使用递归实现.最后只剩余一个元素,也可以看成一个矩阵,不过不…

降低噪声和电磁干扰的原则

1.尽量采用45折线转载于:https://www.cnblogs.com/asulove/p/3827246.html

翻译:java.util.regex.Pattern

java.util.regex.PatternA compiled representation of a regular expression. A regular expression&#xff08;正则表达式&#xff09;, specified as a string, must first be compiled into an instance of this class&#xff08;首先编译成Pattern对象&#xff09;. The…

学习笔记53—Wilcoxon检验和Mann-whitney检验的区别

Wilcoxon signed-rank test应用于两个related samples Mann–Whitney U test也叫Wilcoxon rank-sum test&#xff0c;应用于两个independent samples的情samples size小的时候&#xff0c;是有列表的&#xff0c;sample size大到20左右时&#xff0c;就可以使用正态分布来近似…

s-systemtap工具使用图谱(持续更新)

整体的学习思维导图如下&#xff0c;后续持续更新完善 文章目录安装简介执行流程执行方式stap脚本语法探针语法API函数探针举例变量使用基本应用1. 定位函数位置2. 查看文件能够添加探针的位置3. 打印函数参数&#xff08;结构体&#xff09;4. 打印函数局部变量5. 修改函数局…

2014 Super Training #8 C An Easy Game --DP

原题&#xff1a;ZOJ 3791 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode3791 题意&#xff1a;给定两个0-1序列s1, s2&#xff0c;操作t次&#xff0c;每次改变m个位置&#xff0c;求把s1改变为s2的方法总数。解法&#xff1a; DP&#xff0c;s1和s2哪些位置…

qq分享组件 android,移动端,分享插件

移动端&#xff0c;分享插件发布时间&#xff1a;2018-06-26 10:03,浏览次数&#xff1a;762最近有一个活动页需要在移动端浏览器分享网页到微信&#xff0c;QQ。虽然每一个浏览器都有分享到微信的能力&#xff0c;但不是每个都提供接口供网页来调用。及时有提供&#xff0c;浏…

MySQL中更改表操作

2019独角兽企业重金招聘Python工程师标准>>> 添加一列&#xff1a; alter table t_stu add tel char(20); 删除一个列&#xff1a; alter table t_stu drop column tel; 添加唯一约束&#xff1a; alter table t_stu add constraint uk_srname unique(scode); 添加主…

Maven-环境配置

二更 可算搞好了&#xff0c;除了下面外&#xff0c;我找到了setting.xml里面的东西&#xff0c;给出来就好了&#xff0c;简单就是mvn -v弄好后&#xff0c;setting.xml里面写好的话&#xff0c;直接加入&#xff0c;然后让eclipse下载jar包 然后就可以运行网上的基本项目了 1…

分布式存储(ceph)技能图谱(持续更新)

一下为个人结合其他人对分布式存储 所需的技能进行总结&#xff0c;绘制成如下图谱&#xff0c;方便针对性学习。 这里对分布式存储系统接触较多的是ceph,所以在分布式存储系统分支上偏向ceph的学习。 如有分类有问题或者分支不合理&#xff0c;欢迎大家批评指正&#xff0c;目…

android如何查看方法属于哪个类,Android Studio查看类中所有方法和属性

css-关于位置当你设置一个你想要相对的模块为relative 你这个模块为absolute 则你的这个absolute会相对relative的那个模块进行移动.微信公众平台自动回复wechatlib&period;jar的生成及wechatlib解析微信公众平台出来有一段时日了,官方提供的自动回复的接口调用大致是这么些…

读javascript高级程序设计03-函数表达式、闭包、私有变量

一、函数声明和函数表达式 定义函数有两种方式&#xff1a;函数声明和函数表达式。它们之间一个重要的区别是函数提升。 1.函数声明会进行函数提升&#xff0c;所以函数调用在函数声明之前也不会报错&#xff1a; test(); function test(){ alert(1); } 2.函数表达式不会进行函…

集成公司内部的多个子系统(兼容B/S和C/S),实现单点登录功能的多系统的统一入口功能...

有一句话也挺有意思的&#xff0c;一直在模仿但从未超越过&#xff0c;文章里的技术也都是相对简单的技术&#xff0c;但是实实在在能解决问题&#xff0c;提高效率。现在人都懒得瞎折腾&#xff0c;能多简单就多简单&#xff0c;谁都不希望总是做一些重复的工作&#xff0c;我…

mysql无法远程连接

在mysql的mysql数据库下&#xff1a; select user,host from user;(查看&#xff0c;没有本机的访问权限) grant all privileges on *.* to root"xxx.xxx.xxx.xxx" identified by "密码";(xx为本机ip,%为所有IP) flush privileges; select user,host from …