从零玩转设计模式之工厂方法设计模式-gonchangfangfamoshi

title: 从零玩转设计模式之工厂方法设计模式
date: 2022-12-08 13:22:13.669
updated: 2022-12-11 23:03:22.379
url: http://www.yby6.com/archives/gonchangfangfamoshi
categories: 
- 设计模式
tags: 
- 设计模式

什么是工厂方法模式?

“工厂方法模式”是对简单工厂模式的进一步抽象化,它定义了一种创建对象的方法,允许子类决定实例化哪个类。这样,父类就可以用不同的子类来创建对象,而不需要知道实际创建哪个类。这样可以使得父类与实际创建的子类解耦,从而提高了代码的灵活性和可扩展性。
其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则

为了学习的目的我进行图片形式展现,各位同学请手动打出自己的设计模式代码

代码实现

定义接口实现类

image-1670477994010

创建对应的水果工厂

image-1670478021242

使用

image-1670478076542

代码解析:

        Fruit fruit = new AppleFactory().createFruit();
        fruit.show();

        Fruit banner = new BannerFactory().createFruit();
        banner.show();

这段代码中包含了两个工厂类:AppleFactory 和BannerFactory,它们都实现了同一个接口或抽象类(即 Fruit)中定义的 createFruit() 方法。这个方法被用来创建一个水果(Fruit 类型)的实例。

每个工厂类都有自己的 createFruit() 方法,用来创建不同类型的水果。AppleFactory 类的 createFruit() 方法用来创建苹果(Apple)类型的水果,BannerFactory 类的 createFruit() 方法用来创建香蕉(Banner)类型的水果。

代码中的两行:

Fruit fruit = new AppleFactory().createFruit();
fruit.show();

调用了 AppleFactory 类的 createFruit() 方法来创建一个苹果(Apple)类型的水果实例,并调用这个实例的 show() 方法来展示这个水果。

后面的两行:

Fruit banner = new BannerFactory().createFruit();
banner.show();

也是一样的道理,只不过这次是调用了 BannerFactory 类的 createFruit() 方法来创建一个香蕉(Banner)类型的水果实例,并调用这个实例的 show() 方法来展示这个水果。

这段代码实现了工厂模式,用工厂类来封装了对象的创建过程,并提供了一个统一的接口来访问这些对象。使用工厂类和 createFruit() 方法可以提供一种更灵活、更模块化的方法来创建对象。它允许创建不同类型的 Fruit 对象,而不必指定要创建的对象的确切类。这可以使添加新类型的 Fruit 类和更改代码行为变得更容易,而无需修改现有代码

优缺点

优点
	用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
	灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
	典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
缺点
	类的个数容易过多,增加复杂度
	增加了系统的抽象性和理解难度
	抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。

UML图

image-1670479276667

你的压力来源于无法自律,只是假装努力,现状跟不上内心欲望,所以你焦虑又恐慌。——杨不易
本文转载于网络 如有侵权请联系删除

相关文章

  • cos上传文件报错:ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。

    python方法调用cosapi向cos上传文件时,报错:ConnectionResetError:[WinError10054]远程主机强迫关闭了一个现有的连接。导致文件上传失败代码:#将升级包上传至cos中 logging.basicConfig(level=logging.INFO,stream=sys.stdout) secret_id=''#替换为用户的SecretId secret_key=''#替换为用户的SecretKey region=region#替换为用户的region token=None#如果使用永久密钥不需要填入token,如果使用临时密钥需要填入 scheme='https'#指定使用http/https协议来访问COS,默认为https,可不填 config=CosConfig(Region=region,SecretId=secret_id,SecretKey=secret_key,Token=token,Scheme=scheme) client=CosS3Client(config)

  • PQ-这份数据要按日期和客户分类汇总,怎么办?怎么办?

    小勤:这个数据我要按日期和姓名进行分类汇总,要怎么处理啊?大海:你想怎么分类汇总?小勤:大概像下面这样的效果:大海:还是数据规范的问题啊,数据整理好了,就可以开开心心的数据透视了。小勤:当然啊。但这个日期怎么整成规范的?大海:其实比较简单,导入pq后,添加自定义列,通过判断将日期放到自定义列里面去,然后向下填充就得到完整的日期列了。Step01添加自定义列,提取日期到新列(如果明确其他列为null的即可提取日期,那也可以用if...then...else...进行判断提取)Step02填充日期Step03提升标题行(2次),得到列名并修改新添加的自定义列列名为“日期”Step04通过筛选去掉多余的日期行和标题行(根据实际情况筛选)小勤:原来也挺简单的啊。才几步操作,数据就整理好了,后面进行数据透视就很简单了。大海:嗯。当然是的。但其中提升标题行时会自动添加“更改数据类型”的步骤,这些步骤里将列名固定了,以后如果数据有变化,可能导致找不到这些列的错误:小勤:那该怎么办呢?大海:对于更改的类型步骤,直接删除就好了。小勤:但好像还有个问题,就是新增的列改名为“日期”的步骤,也可能会因为开始的

  • Python3如何判断三角形的类型

    #判断三角形类型deftriangle(a,b,c): ifa0andb0andc0: ifa+bcandb+caanda+cb: ifa==bandb==c: return("这是等边三角形") elifa==borb==corc==a: return("这是等腰三角形") else: return("这是不规则三角形") elifa+b==corb+c==aora+c==b: return("这是个直角三角形") else: return('这好像不是个三角形') else: return("请输入大于0的数字")复制补充知识:python:输入三个数判断是什么三角形刚刚学习Python,欢迎大家指点#Filename:Triangle #Function:Judgmenttriangle #Author:Judy #Time:2018.9.26 a=int(input("Pleaseinputthefirstside:"))#输入第一条边

  • 【一起学源码-微服务】Nexflix Eureka 源码九:服务续约源码分析

    前言前情回顾上一讲我们讲解了服务发现的相关逻辑,所谓服务发现其实就是注册表抓取,服务实例默认每隔30s去注册中心抓取一下注册表增量数据,然后合并本地注册表数据,最后有个hash对比的操作。本讲目录今天主要是看下服务续约的逻辑,服务续约就是client端给server端发送心跳检测,告诉对方我还活着。现在很多分布式系统都会有心跳检查的机制,这里一起来学习下Eureka是怎么做心跳检查的。目录如下:client端心跳检查调度任务server端接收心跳检查,设置最后renew时间这一讲内容不太多,因为上一篇文章写全量和增量注册表信息内容有点多,所以这里将博客尽量一篇保持一个知识点,后面还会讲服务实例下线、摘除、注册中心自我保护等机制的实现原理。源码分析client端心跳检查调度任务服务实例续约代码比较简单,这里还是从DiscovertClient.java开始,很多源码的入口都是在这里,因为client端初始化、注册都是走的这里,因为前几篇文章对这个类已经分析很多了,这里只截取部分重要代码:DiscovertClient.java初始化后会继续初始化一些调度任务:privatevoidini

  • 如果用python利用本地sendmai

    来自于http://stackoverflow.com/questions/73781/sending-mail-via-sendmail-from-python #Importsmtplibfortheactualsendingfunction importsmtplib #Importtheemailmoduleswe'llneed fromemail.mime.textimportMIMEText #Openaplaintextfileforreading.Forthisexample,assumethat #thetextfilecontainsonlyASCIIcharacters. fp=open(textfile,'rb') #Createatext/plainmessage msg=MIMEText(fp.read()) fp.close() #me==thesender'semailaddress #you==therecipient'semailaddress msg['Subject']=

  • 性能专题:一文搞懂性能测试常见指标

    1.前言 上周,对性能测试系列专题,在公号内发表了第一篇介绍:【性能系列连载一】开篇:性能测试不可不知的“干货”,但反响貌似并不太好,但既然此前已答应了部分读者要连载分享性能这块的知识,含着泪也得继续写。性能测试的基础:就是在确保功能实现正确的前提下,通过合适的性能测试加压方式和策略,并收集考察服务端应用程序的各项性能指标,以及服务器硬件资源的使用情况,来评估是否存在性能问题隐患。那今天作为性能测试系列的第二篇,主要会为大家介绍在服务端性能测试中,常见的性能指标有哪些。2.性能指标分类从性能测试分析度量的度角来看,可以从如下几个维度来收集考察各项性能指标:系统性能指标资源性能指标中间件指标数据库指标稳定性指标可扩展性指标可靠性指标下面将从如上这几个维度,分别从各自维度常见指标,以及指标含义、指标行业参考标准等方面进行介绍。3.系统性能指标系统性能指标,常见的可从如下几类进行参考:响应时间系统处理能力吞吐量并发用户数错误率3.1响应时间定义和解释:响应时间,简称RT。是指系统对请求作出响应的时间,可以理解为是指用户从客户端发起一个请求开始,到客户端接收到从服务器端返回的响应结束,整个过程

  • 腾讯云大学大咖分享 | 深入浅出话智能语音识别

    语音识别就是把语音变成文字的过程,相信大家在平时生活也已经用到过一些语音识别的场景,比如说语音输入法、地图产品的语音输入。近年来,随着互联网的发展,各种音频数据和文本数据得到不断积累和丰富,CPU、GPU硬件的发展,以及深度学习算法大规模的应用,语音识别技术的应用开始获得大规模的商业化拓展。此次我们整理了腾讯云大学大咖直播课《智能语音技术解密》的回顾,帮助大家了解智能语音,以及智能语音背后的一些技术。一、智能语音识别的过程:机器识别语音到文字的过程和人识别语音的过程类似:从录音文件或是麦克风收集的音频中提取特征,经过声学模型和语言模型的处理,最后得出的是识别结果的文字。提取特征的方式有很多种,比较常见的是MFC(多频互控)。在这个过程中,我们将重点关注特征提取、声学模型、语言模型这三个流程。特征提取方面:我们在拿到一段音频文件后,会先把这个文件进行转码变成PCM格式,然后把这个文件分成一片一片,也就是分帧,再对每一帧的数据进行采样。声学模型方面:提取了特征之后,就要进行声学模型的处理。这个过程就是把之前提取到的发音特征数据变成音素概率。语言模型方面:语言模型的处理需要大量的文本语料,通

  • vuex入门学习笔记

    前言我们需要解决多个组件间的数据通信和状态管理就显得难以维护的问题,在vue中用的是vuex,在react中用的是redux.通过本篇教程将基本熟悉它的所有常用用法以及注意事项。用于解决什么问题?用于解决组件之间数据共享,数据的集中处理。什么是vuex?单项数据流基本使用#安装 npminstall--savevuex #引入一般我们会在src根目录下创建一个store的文件夹, #下面写index.js来实现相关的存储方法(组件共用数据) importVuexfrom'vuex' importVuefrom'vue' Vue.use(Vuex)复制vuex的组成部分(应用结构)StateState负责存储整个应用的状态数据,一般需要在使用的时候在跟节点注入store对象,后期就可以使用this.$store.state直接获取状态。一般是在main.js文件中引入store的文件,从而使用。(vuespa应用中)//store为实例化生成的 importstorefrom'./store' newVue({ el:

  • MongoDB安装非关系性数据库MongoDBMongoDB安装

    非关系性数据库NoSQL,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。 MongoDBMongoDB数据库也是一种非关系性数据库,对于爬虫爱好者来说,把数据插入MongoDB也是一个不错的选择,今天学习下安装MongoDB(win7)。MongoDB安装进入MongoDB官网,点击download进行下载。 下载电脑相应的版本 打开安装文件进行安装MongoDB需要指定数据库的安装位置,我们在mongodb文件夹下新建data文件夹,在data文件夹下新建db文件夹。 在mongodb的bin文件夹下运行命令窗口,输入mongod--dbpathD:\mongodb\data\db复制指定数据库存放位置 6.输入下面命令启动mongodb服务mongo复制

  • 第一章:权限管理设计基础——深入浅出学Shiro细粒度权限开发框架

    为了让大家更好的理解后面讲述的知识,先介绍一点权限系统的基础知识: 几乎所有的权限系统都分成两个部分,一个是分配权限部分,一个是验证权限部分,为了理解它们,首先解释两个基本的名词:安全实体和权限。 安全实体:就是被权限系统保护的对象,比如工资数据。 权限:就是需要被校验的权限对象,比如查看、修改等。n安全实体和权限通常要一起描述才有意义: 比如有这么个描述:“现在要检测登录人员对工资数据是否有查看的权限”,“工资数据”这个安全实体和“查看”这个权限一定要一起描述。如果只出现安全实体描述,那就变成这样:“现在要检测登录人员对工资数据”,对工资数据干什么呀,没有后半截,一看就知道不完整;当然只有权限描述也不行,那就变成:“现在要检测登录人员是否有查看的权限”,对谁的查看权限啊,也不完整。所以安全实体和权限通常要一起描述。n了解了上面两个名词,来看看什么是分配权限和验证权限:所谓分配权限是指:把对某些安全实体的某些权限分配给某些人员的过程。所谓验证权限是指:判断某个人员或程序对某个安全实体是否拥有某个或某些权限的过程。 也就是说,分配权限过程即是权限的分配过程,而验证权限过程则是权限的匹配过

  • 天猫魔盒2评测报告

    文章目录[隐藏]天猫魔盒2评测报告1.设计做工(15分)2.接口及配件(15分)2.1接口(8分)2.2配件(7分)3.功耗(5分)3.1待机功耗(不计分)3.2播放本地视频功耗(不计分)3.3软关机功耗(5分)4.性能(35分)4.1安兔兔测试(13分)4.2安兔兔视频测试(12分)4.3分辨率支持(5分)4.4无线性能(5分)5.系统平台(40分)5.1用户体验(9分)5.2内容平台(31分)总结在reizhi网络机顶盒评测标准发布之后,机顶盒的评测工作也同期展开了。第一款测试的机顶盒是天猫魔盒2,选取它的原因大概是因为亲切感,毕竟reizhi自己有一台天猫魔盒1。与之前不同的是,天猫魔盒2彻底改变了方形外观设计,转为使用圆形模具。虽然圆形外壳美观度更高,但却导致了电路板设计难度的增加,同时空间利用率比方形外壳更低。此前我们有谈到,品相较好的机顶盒更能够激起消费者的购买欲,天猫魔盒2在这一点上无疑做得非常出色。天猫魔盒2评测报告1.设计做工(15分)天猫魔盒2采用了时下广为流行的浅黄色硬纸盒包装,采用烫金工艺将产品名称以及LOGO标注于包装盒正面。包装设计虽简洁但却略显单调乏味,本

  • js判断字符串数组是否包含某个字符串_怎么判断数组有几个元素

    方法一:indexOf(item,start)Item:要查找的值; start:可选的整数参数,缺省则从起始位子开始查找。indexOf()返回元素在数组中的位置,如果没有则返回-1,该方法只能查找字符串,数字等,不能查找类或者数组或者NaN,如果想查找类或者数组,可以使用下面介绍的其他方法;vararr=['a','b','c','d']; console.log(arr.indexOf('b')); //1 console.log(arr.indexOf('ab'));//-1 //一般情况下判断元素是否存在 if(arr.indexOf('查找的元素')>-1){ //元素存在 }复制方法二:arr.find() arr.find()的参数是一个回调函数,数组内所有元素会遍历这个回调函数,直到找到第一个返回值为true的元素,然后返回该元素,否则返回undefined。 find()数组中的每一个元素都会调用一次函数,但是当条件返

  • List的同步类比较

    TL;NRs CopyOnWriteArrayList类在多线程顺序读取上有很大的优势,但在随机读取上反而有较大的劣势,且在写入方面性能极差。 Vector类在顺序读取方面性能较差,但在随机读取方面有较大的优势,写入方面性能也还可以。 1,引言 java线程安全的List实现有以下三种: newVector<>() Collections.synchronizedList(newArrayList<>()) newCopyOnWriteArrayList<>() 通常认为使用了synchronized会导致运行变慢,那么在java针对synchronized进行一系列优化后,现在的情况如何呢?为了检验这一说法,写了一个验证程序进行验证。 2,验证代码 以ArrayList作为基础,分别测试4种List的顺序写入(0~1<<24)、顺序读取和随机读取,各十轮。据此编写代码。代码太长了,所以放到最后 3,测试平台 垃圾笔记本,使用Intel酷睿i57200U java版本为java12,HotSpot虚拟机 4,测试结果 单位:毫秒

  • 搜索框 sug 基本技术方案

    一、候选sug词数据来源: 商品侧:query召回的商品数、query召回的订单数 query侧:QV、QV_CTR、QV_CXR 从这两个角度选出的query作为sug词候选集 二、数据处理(分析) 规则挖掘、FP算法挖掘、商品标题NER标签提取:功效/品牌/适用群体/适用场景+简名 三、sug词召回 query:商品侧vsquery侧 query处理:原始query(未处理)vs改写query 原始query/改写query-->分词-->基于分词结果从候选集中进行前缀召回 原始query/改写query-->拼音前缀匹配召回 原始query/改写query-->连续子串匹配召回 四、排序 query侧召回的词>商品侧召回的词 搜索PV 固定指标:QV_CTR/QV_CXR 五、评价指标 sug词点击率 搜索框点击跳出率 相关产品功能的转化指标等 六、工程技术方案 https://github.com/hankcs/AhoCorasickDoubleArrayTrie双数组字典树,key是查询词,value支持对象(sug结果词+各种指标(搜索uv、Q

  • dns欺骗-复现

    一、实验名称: dns欺骗 二、实验环境: (实验的系统配置、比如CPU、操作系统、攻击机/靶机IP地址等参数) VMwareWorkstationPro、kali2019-04、Windowsxp 三、实验原理: (实验对应的原理和基础知识描述) 如果可以冒充域名服务器,然后把查询的IP地址设为攻击者的IP地址。 这样的话,用户上网就只能看到攻击者的主页,而不是用户想要取得的网站的主页了,这就是DNS欺骗的基本原理。 DNS欺骗其实并不是真的“黑掉”了对方的网站,而是冒名顶替、招摇撞骗罢了。 四、实验步骤: Windowsxp:192.168.73.129 Kali:192.168.73.131 网关:192.168.73.2 1-首先打开ettercap的DNS文件进行编辑,在kalilinux2.0下的文件路径为/etc/ettercap/etter.dns(命令:vim/etc/ettercap/etter.dns) 2-在对应的位置添加对应的标识和IP地址 *代表所有域名后边就是你要欺骗为的IP地址。(vim基本上vi可以分为三种状态,分别是命令模式(command

  • Unity 常用扩展方法,持续更新中

    这里总结了一些提高开发效率的扩展方法,放到一个类里了,可以直接拿取用,会持续更新着,也欢迎大家留言一些有用的扩展方法,大家一起维护,我更新到这个类里   usingSystem.Collections; usingSystem.Collections.Generic; usingUnityEngine; usingUnityEngine.Events; usingUnityEngine.EventSystems; ///<summary> ///常用的扩展方法 ///</summary> publicstaticclassMethodExtend { #regionVector publicstaticstringToFullString(thisVector2v2) { returnstring.Format("[{0},{1}]",v2.x,v2.y); } publicstaticstringToFullString(thisVector3v3) { returnstring.Format("[{0},{1},{2}]",v3.x,v3.y,

  • lua post参数获取,参数截断

    post请求头:   a.application/x-www-form-urlencoded普通表单提交   b.multipart/form-data 含有文件的表单,二进制上传   c.application/json将参数json字符串格式放入body上传,客户端自己解析 openresty接收post参数时必须ngx.req.read_body()读取body,但在解析不同请求头数据时还有区别:   a.application/x-www-form-urlencoded 调用ngx.req.get_post_args()获取参数   b.multipart/form-data    c.application/json通过调用ngx.req.get_post_args()获取参数时,参数被openresty处理为{"json参数":true}的格式(被包装成一个map对象的key),而且当json参数包含'='时会发生参数截断,丢失'='后面的数据;但通过ngx.req.get_body_data()则可以直接拿到json参数的字符串,直接反序列化

  • 打包Winform后安装在C盘权限不足的解决方法

    打包安装到C盘,打开快捷方式,提示对路径***的访问被拒绝 解决方法: (1)VS中右键项目=》属性=》安全性,勾选【启用ClickOne安全设置】; (2)找到app.manifest,将 <requestedExecutionLevellevel="asInvoker"uiAccess="false"/>修改为 <requestedExecutionLevellevel="requireAdministrator"uiAccess="false"/>(3)再次找到项目属性的安全性,去掉【启用ClickOne安全设置】的勾选; (4)保存后编译,再次打包

  • 危险代码:如何使用Unsafe操作内存中的Java类和对象

    危险代码:如何使用Unsafe操作内存中的Java类和对象—Part1 危险代码:如何使用Unsafe操作内存中的Java类和对象—Part2 危险代码:如何使用Unsafe操作内存中的Java类和对象—Part3 危险代码:如何使用Unsafe操作内存中的Java类和对象—Part4 DangerousCode:HowtobeUnsafewithJavaClasses&ObjectsinMemory

  • 洛谷P3951小凯的疑惑/[蓝桥杯 2013 省] 买不到的数目

    看了洛谷中的各个题解,感觉除了exgcd都很突兀没什么思路的... 感觉这个解法对于我来说还算有点循序渐进的过程... 首先我们应该会考虑一个问题: 为什么从某个数开始,它之后的每个数都能被线性表示. 我们假设a<b(反了就swap一下) 设k满足ka<b&&(k+1)a>b(没有等于是因为gcd==1) 那么前k个能表述的元素的相邻的两个元素之间的差为a 第k个和第k+1个元素(也就是b)之间的差为b%a(b=ka+d差就是d) 第k+1个和第k+2个元素之间的差为a-b%a  第k+2个和第k+3个元素之间的差为b%a(因为第k+3个元素是b+a) 那么在从xb到xb+a这一段如果有一个空位不能被填满那么这个空位将一直持续直到某一次取模时把这个空位填满 那么什么时候能把空位全部填满了,后面的每一个数也就能被线性表示了 什么时候能填满呢 ∵gcd(a,b)=1 ∴gcd(a,b%a)=1 ∴lcm(a,b%a)=a*(b%a) 那么感性理解一下就可以知道每一轮都会有一个新的余数被填入上述的空位 总共有1到a-1,a-1个空位 那么就要轮a-

  • sqlite下划线,like中不能匹配下划线的问题

    使用like语句的错误查询 select*fromtwherexlike'%_%'; 返回全部的记录,不是想要的结果!   为什么错误? 因为在like语句中的下划线的含义是“任意一个字符”,类似“%”代表匹配任意多个字符的。   4.正确的查询方法 能想到的有如下两种方法。 1)第一种方法使用escape转义 mysql>select*fromtwherexlike'%\_%'escape'\'; 返回包含有"_"的记录,正确   escape的内容可以任意,只要保证前后一致即可。 mysql>select*fromtwherexlike'%|_%'escape'|'; 返回包含有"_"的记录,正确   mysql>select*fromtwherexlike'%*_%'escape'*'; 返回包含有"_"的记录,正确   2)使用instr函数辅助判断 使用instr函数判断字段中是否包含“_”,如果包含返回值是非零的,如果不包含则返回值是零。 mysql>select*fromtwhereinstr(x,

相关推荐

推荐阅读