Java设计模式-创建者模式-工厂模式

工厂模式

  • 工厂模式
    • 简单工厂模式
    • 工厂方法模式
    • 抽象工厂模式

工厂模式

要求:由一个特定的工厂提供所需的对象,由工厂来完成对象的创建
工厂模式一般分为三种:简单工厂模式工厂方法模式抽象工厂模式
其中简单工厂模式不属于23种设计模式

简单工厂 : 用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)
抽象工厂 :用来生产不同产品族的全部产品。(支持拓展增加产品;支持增加产品族)

简单工厂模式

简单工厂模式就是 定义了一个创建对象的类,让这个类来封装实例化对象的行为
特点:只有一个工厂,根据入参,通过硬编码的方式创建所需对象。不方便扩展,不建议用
假设:我要开一个小店,卖牛肉包子,猪肉包子
分析上述需求,我们用简单工厂模式实现,如下:

/*** 抽象包子类**/
public interface Bun {void pack();//打包
}/*************************************************************************/public class BeefBun implements Bun {public BeefBun() {System.out.println("包牛肉包");}@Overridepublic void pack() {}
}/*************************************************************************/
public class PorkBun implements Bun {public PorkBun() {System.out.println("包猪肉包");}@Overridepublic void pack() {}
}/*************************************************************************/
/*** 简单包子工厂**/
public class BunFactory {public Bun createBun(String type){Bun bun = null;switch (type){case "beef":bun = new BeefBun();break;case "pork":bun = new PorkBun();break;default:throw new RuntimeException("我不会做");}return bun;}
}

上述代码通过包子工厂 BunFactory,根据入参选择生产不同种类的包子,实现了工厂模式,隐藏了生产细节
测试代码如下:

public class MyStore01 {/*** 简单工厂模式* 只有一个工厂*/BunFactory factory = new BunFactory();public Bun order(String type){Bun bun = factory.createBun(type);//打包...等操作bun.pack();return bun;}
}/*************************************************************************/
@Test
public void client01(){MyStore01 myStore = new MyStore01();Bun beef = myStore.order("beef");Bun pork = myStore.order("pork");
}
输出:
包牛肉包
包猪肉包

上述代码完成了简单工厂模式的使用,可以隐藏实例的创建,通过工厂对实例进行创建。
但是设想一下,如果需要扩展功能怎么办
假设,我的小店 又要做 香菇菜包,那么势必要修改 BunFactory的代码,很明显,这违反了开闭原则。
那么接下来我们看下 工厂方法模式

工厂方法模式

定义多个工厂,每个工厂生产一种产品
特点:有多个工厂,工厂抽象化,一个具体工厂只生产一个具体产品,容易类爆炸
还是针对上面的需求,开一个小店,卖牛肉,猪肉包子
使用工厂方法模式,实现如下:

/*** 抽象包子类**/
public interface Bun {void pack();//打包
}/*************************************************************************/public class BeefBun implements Bun {public BeefBun() {System.out.println("包牛肉包");}@Overridepublic void pack() {}
}/*************************************************************************/
public class PorkBun implements Bun {public PorkBun() {System.out.println("包猪肉包");}@Overridepublic void pack() {}
}/*************************************************************************/
/**
* 抽象包子工厂
*/
public interface BunFactory {Bun createBun();
}/*************************************************************************/
/**
* 牛肉包子工厂
*/
public class BeefBunFactory implements BunFactory{@Overridepublic Bun createBun() {return new BeefBun();}
}/*************************************************************************/
/**
* 猪肉包子工厂
*/
public class PorkBunFactory implements BunFactory {@Overridepublic Bun createBun() {return new PorkBun();}
}

测试代码:

public class MyStore02 {/*** 工厂方法模式* 有多个工厂,一个工厂只产一种产品* @param type* @return*/BunFactory factory;public void setFactory(BunFactory factory) {this.factory = factory;}public Bun order(){Bun bun = factory.createBun();//打包...等操作bun.pack();return bun;}
}@Test
public void client02(){MyStore02 myStore = new MyStore02();myStore.setFactory(new BeefBunFactory());myStore.order();myStore.setFactory(new PorkBunFactory());myStore.order();
}输出:
包牛肉包
包猪肉包

上述代码完成了 和简单工厂模式相同的功能,
但是使用工厂方法模式,可以不修改原有代码,通过增加工厂类的方式来扩充功能。

例如:我想增加青菜包的业务,只需要实现一个青菜包类 和 青菜包工厂即可

但是,我们再想一下,新增一个功能要加两个类,如果后面业务越来越广泛,类是不是越来越多,是不是 容易类爆炸。
再思考一下,一个工厂只生产一种产品是不是太浪费了。难道又要回到简单工厂模式了?

当然不是,我们可以折中一下,对工厂类进行更深层的抽象。对产品进行划分,让一个工厂可以生产多种产品,这些产品都是同一组的,相关联的。

下面看下抽象工厂模式

抽象工厂模式

提供一个生产一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

抽象工厂模式比工厂方法模式的抽象程度更高。在工厂方法模式中每一个具体工厂只需要生产一种具体产品,但是在抽象工厂模式中一个具体工厂可以生产一组相关的具体产品,这样一组产品被称为产品族。产品族中的每一个产品都分属于某一个产品继承等级结构。

特点:多个工厂,工厂进行更高层次的抽象,每个工厂生产一个产品族(生产一组相关的具体产品

先引入两个概念:产品族,产品等级结构

  • 产品族:一组相关的具体产品(如海尔旗下的众多产品)。
  • 产品等级结构:每一个产品族都分属于某一个产品继承等级结构(如空调下的多种品牌)。

在前面的工厂方法模式中,考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机。工厂方法模式只考虑生产同等级(同种类被称为同等级)的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如农场里既养动物又种植物,电器厂既生产电视机又生产洗衣机或空调。而抽象工厂模式就考虑了多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,如图所示的是海尔工厂和 TCL 工厂所生产的电视机与空调对应的关系图。
在这里插入图片描述
还是针对我的包子店的需求,我扩充了牛奶的需求。
使用抽象工厂模式开发如下:


/*** 抽象包子类**/
public interface Bun {void pack();//打包
}/*************************************************************************/public class BeefBun implements Bun {public BeefBun() {System.out.println("包牛肉包");}@Overridepublic void pack() {}
}/*************************************************************************/
public class PorkBun implements Bun {public PorkBun() {System.out.println("包猪肉包");}@Overridepublic void pack() {}
}/*************************************************************************/
/**
*抽象牛奶类
*/
public interface Milk {void pack();//打包
}/*************************************************************************/
public class PureMilk implements Milk{public PureMilk() {System.out.println("做一杯纯牛奶");}@Overridepublic void pack() {}
}/*************************************************************************/
public class BreakfastMilk implements Milk{public BreakfastMilk() {System.out.println("做一杯早餐奶");}@Overridepublic void pack() {}
}/*************************************************************************/
/**
*抽象工厂类
*/
public interface Factory {Bun createBun();Milk createMilk();
}/*************************************************************************/
/**
*具体工厂类1号,生产牛肉包和纯牛奶
*/
public class PureBeefFactory implements Factory{@Overridepublic Bun createBun() {return new BeefBun();}@Overridepublic Milk createMilk() {return new PureMilk();}
}/*************************************************************************/
/**
*具体工厂类2号,生产猪肉包和早餐奶
*/
public class BreakfastPorkFactory implements Factory{@Overridepublic Bun createBun() {return new PorkBun();}@Overridepublic Milk createMilk() {return new BreakfastMilk();}
}

上述代码中,纯牛奶和牛肉包被看作一个产品族
纯牛奶和早餐奶被看成一个产品等级结构
测试代码:

public class MyStore03 {/*** 抽象工厂模式* 有多个工厂,一个工厂生产一个产品族* @param type* @return*/Factory factory;public void setFactory(Factory factory) {this.factory = factory;}public Bun orderBun(){Bun bun = factory.createBun();//打包...等操作bun.pack();return bun;}public Milk orderMilk(){Milk milk = factory.createMilk();milk.pack();return milk;}
}/*************************************************************************/
/*** 抽象工厂模式*/
@Test
public void client03(){MyStore03 myStore = new MyStore03();myStore.setFactory(new PureBeefFactory());myStore.orderBun();myStore.orderMilk();
}
输出:
包牛肉包
做一杯纯牛奶

上述抽象工厂实现了一个工厂创建多个产品的功能,与简单工厂类似,自然有简单工厂类似的缺点:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

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

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

相关文章

10-26 maven配置

打开idea 打开setting 基于Idea创建idea项目 加载jar包:(一般需要自己去手动加入,本地仓库是没有的)

Zookeeper选举Leader源码剖析(上)

为什么要看源码: 1、 提升技术功底: 学习源码里的优秀设计思想,比如一些疑难问题的解决思路,还有一些优秀的设计模式,整体提升自己的技术功底 2、 深度掌握技术框架: 源码看多了,对于一个新技…

AT32F403A VGA(一)

一、目的: 要用单片机实现VGA功能。 二、分析: VGA需要两根时钟信号线,分别为Hsync和Vsync。 在800*600的显示模式下,Hsync周期为26.4us,Vsync周期为16.579ms。 Hsync同步脉冲时间为3.2us,Vsync同步脉…

【23真题】太难!千万别考!不值!

今天分享的是23年哈尔滨工程大学810的信号与系统试题及解析。 为什么说不值呢?因为哈工程810据之前的分析来看不保护一志愿,就23年810的专业课来看,又在超纲的边缘疯狂试探!(如果它默认考DSP,当我没说&…

Xmake v2.8.5 发布,支持链接排序和单元测试

Xmake 是一个基于 Lua 的轻量级跨平台构建工具。 它非常的轻量,没有任何依赖,因为它内置了 Lua 运行时。 它使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好&#x…

为什么OpenAPI是未来企业数字化转型的决定性因素

随着数字经济不断发展升级,数据互通、万物互联正在逐步成为IT产业发展的主旋律,企业数字化转型也变得愈发紧迫。越来越多的企业都在数字化转型过程中寻求降本增效、加大创新力度、开展生态合作,以此来提高企业和产品的持续竞争力。而OpenAPI则…

golang正则获取中括号中的内容

reg : regexp.MustCompile("【(.*?)】") //userInfo姓名:【AAA姓名】证件类型:【BBB身份证】证件号码:【122456789458】tempData reg.FindAllStringSubmatch(userInfo, -1)for k, v : range tempData {if k 0 {tempReleaseUser.Name v[1]//AAA姓名} else if k 1…

数据结构与算法C语言版学习笔记(5)-串,匹配算法、KMP算法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、串的定义二、串的存储结构1.顺序结构2.链式结构 三、串的朴素的模式匹配算法(暴力匹配算法)1.背景2.假设我们要从下面的主串 S"…

Spring boot 整合grpc 运用

文章目录 GRPC基础概念:Protocol Buffers:proto 基础语法:调用类型: Spring boot 整合 grpc项目结构:整合代码:父 pomproto 模块服务端:客户端:实际调用: 原生集成 GRPC基…

leetcode链表

这几天手的骨裂稍微好一点了,但是还是很疼,最近学校的课是真多,我都没时间做自己的事,但是好在今天下午是没有课的,我也终于可以做自己的事情了。 今天分享几道题目 移除链表元素 这道题我们将以两种方法开解决&…

Project Office X for Mac项目管理工具

Project Office X是一款全能的项目管理软件,可帮助企业或个人有效地规划、协调和执行项目。它具有直观的用户界面和强大的功能,适用于各种规模的项目。 这个软件提供了多种实用工具,包括项目计划、资源管理、任务分配、进度跟踪、风险管理和团…

在Node.js中,什么是Promise?如何使用Promise处理异步操作?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

两台Linux服务器之间传送文件

两台Linux服务器之间传送文件 将U盘上的数据传送到服务器上 本地U盘 远程服务器地址: 192.168.30.125 传送到data文件夹的下面 scp -r coco2017 s192.168.30.125:/data传送 两台Linux服务器之间传送文件的4种方法

2024上海智博会,上海国际智慧城市,物联网,大数据展会(世亚智博会)

中国国际智慧城市,物联网,大数据博览会(简称:世亚智博会)自2010年创办以来,至今已成功举办十多届。世亚智博会是中国较高、规模较大、影响力较广的展会;是被国际业界公认的不可错过的名展之一。随着世亚智博会的国际地位和影响不断…

Linux 入门

Linux 入门 1:linux 用户 root 用户 :也叫超级用户,UID0,其权限最高。系统用户:也叫虚拟用户,UID 1-999普通用户: UID1000-60000, 可以登录系统,操作自己目录下的文件. 1.1:用户操作命令 切换用户: su …

PHP+MySQL人才招聘小程序系统源码 带完整前端+后端搭建教程

在当今竞争激烈的人才市场中,招聘平台的需求日益增长。传统的招聘平台往往需要投入大量的人力物力进行维护和管理,这对于许多中小企业来说是一个沉重的负担。因此,开发一个简单易用、高效便捷的招聘平台显得尤为重要。 PHP是一种流行的服务器…

配置Linux为无线路由器

配置Linux无线路由器 将Linux配置为无线路由器。使用hostapd,可以配置无线网卡为AP模式。 这里使用buildroot来生成这个工具。Wi-Fi模块使用的是 rt8188eus。 1. 内核配置 2. buildroot配置 开启 rt8188eus 驱动 3. 启动hostapd 系统启动后,会自动加…

实用技巧:嵌入式人员使用http服务模拟工具模拟http服务器测试客户端get和post请求

文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/134305752 红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结…

程序员35岁之后如何规划?建议收藏!

文章目录 一、年纪大能不能进大厂?二、为什么说35是危机? 1.精力衰退2.脑力衰退3.知识/技术迭代 三、年龄大的程序员有哪些出路? 1.技术管理2.创业3.技术外包4.做老师5.做自媒体6.写书 四、结语 我自己今年已有44了,从2021年开始…

【Linux语音控制 安卓设备刷短视频 orangePi zero2 H616 (已开源) 】.md uptada:23/11/07

文章目录 H616_实现Ubuntu语音控制安卓设备刷短视频小美效果展示H616 ubuntu系统 安装adb智能公元 SU-03T 离线语音模组 固件制作配合串口实现 小美_控制安卓刷抖音 H616_实现Ubuntu语音控制安卓设备刷短视频 注意:orangePi zero2 H616 安装系统为ubuntu 小美效果…