当前位置: 首页 > news >正文

设计模式——工厂模式(简单工厂、工厂方法、抽象工厂)

是什么?

工厂模式的目的是将创建对象的具体过程隐藏起来,从而达到更高的灵活性

工厂模式分为:简单工厂模式、工厂方法模式、抽象工厂模式

为什么?

在Java中,万物皆是对象,我们在使用的时候这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,那么所有new的地方都需要修改一遍,这明显违背了设计原则中的开闭原则,如果我们使用工厂来生产对象,那么我们只需要和工厂打交道就好了,彻底和对象解耦,如果要更换对象,直接在工厂中更换该对象即可,达到了与该对象解耦的目的,因此工厂模式最大的优点就是:解耦

简单工厂模式

简单工厂不是一个设计模式,它更像是一种编码习惯

结构

抽象产品:定义了产品的规模,描述了产品的主要特性和功能。

具体产品:实现或者继承抽象产品的子类。

具体工厂:提供了创建产品的方法,调用者通过该方法来获取产品。

实现

产品类:

public class Car {  //汽车父类private String getName;}
public class Tesla extends Car{   //子类-特斯拉汽车public Tesla() {System.out.println("()=>制造特斯拉汽车");}
}
public class Benz extends Car{  //子类-奔驰汽车public Benz() {System.out.println("()=>制造奔驰汽车");}
}

工厂类及用户使用:

public class SimpleFactory {/*** 。模拟简单工厂模式* */public Car getCar(String type){    //汽车“生产间”=》简单工厂if ("Benz".equals(type)){return new Benz();}if ("Tesla".equals(type)){return new Tesla();}return new Car();}
}
public class Customer {//消费者直接调用的是工厂而非对象本身,这样就将用户和创建对象的过程隔离开来了public static void main(String[] args) {SimpleFactory simpleFactory = new SimpleFactory();simpleFactory.getCar("Benz");}
}

优缺点

我们会发现,在简单工厂模式中,提供了专门的工厂类来帮助我们创建对象,实现了对象创建和用户使用的职责分离,客户端不需要知道所创建的产品类名以及创建过程只需要知道具体产品类所需要的参数即可,通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性;

但是这样做也是不符合“开闭原则的”,如果我们这个时候需要再添加一个BMW汽车,那么同样的需要去修改我们的工厂类,在产品类型较多的时候,有可能造成工厂逻辑过于复杂,不利于系统的横向扩展和维护,并且工厂类集中了所有产品的创建逻辑,如果不能正常工作那么整个系统都会受到影响

为了解决简单工厂出现的问题,引入了我们的工厂方法模式

工厂方法模式

定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象,工厂方法使一个产品类的实例化延迟到其工厂的子类;

结构

抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品;

具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建;

抽象产品:定义了产品的规范,描述了产品的主要特性和功能;

具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应;

实现

产品类:

public class Car {// 产品父类}public class Benz extends Car{  //子类产品public Benz() {System.out.println("()=>制造奔驰汽车");}
}
public class Tesla extends Car{   //子类产品2public Tesla() {System.out.println("()=>制造特斯拉汽车");}
}

抽象工厂

public interface AbstractFactoryInterface {  //抽象工厂Car createCar();
}

具体工厂及用户使用

public class BenzFactory implements AbstractFactoryInterface{  //具体子类工厂@Overridepublic Car createCar() {return new Benz();}
}public class TeslaFactory implements AbstractFactoryInterface{  //具体子类工厂2@Overridepublic Car createCar() {return new Tesla();}
}
public class Customer {   //用户类public static void main(String[] args) {Car car = new BenzFactory().createCar();Car car2 = new TeslaFactory().createCar();}
}

那么我们这个时候还需要添加一个BMW车的话,只需要创建一个BMW类去继承Car,并且再去创建一个BMW的工厂去实现抽象工厂即可,不需要去修改原来的代码,问题即得到解决;

优缺点

用户只需要知道具体工厂的名称即可得到所要的产品,也不需要知道产品具体的类和创建过程,在系统增加新的产品的时候只需要添加具体产品类和对应具体工厂类,无需对源代码进行任何修改,满足开闭原则;

但是每增加一个产品就需要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度;

抽象工厂模式

我们前面介绍的工厂方法模式中考虑的是一类产品的生产,如车厂只生产车,畜牧场只生产动物;

这些工厂只生产同种类的产品,也就是说工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂都是综合型的工厂,能够生产多等级的产品,例如一个畜牧场它不仅生产动物,还生产饲料粮食,汽车厂不仅生产汽车,还生产发动机、汽车配饰等等;

因此抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族如下:横轴是产品等级,也就是同一类产品,纵轴是产品族,也就是同一品牌的产品(产自同一个工厂);

也就是说它是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构;

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可以生产多个等级的产品;

结构

抽象工厂:提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品;

具体工厂:主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建;

抽象产品:定义了产品的规模,描述的产品的主要特性和功能,抽象工厂模式中有多个抽象产品;

具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它与具体工厂之间是多对一的关系;

实现

也就是说我们现在车厂不仅要生产车,还要生产车的配饰、配件等等;

抽象产品及具体产品

public class Engine {public Engine() {}
}public class V12Engine extends Engine{public V12Engine() {System.out.println("这是V12发动机");}
}public class V8Engine extends Engine{public V8Engine() {System.out.println("这是V8发动机");}
}public class Acc {public Acc() {}
}
public class Cowhide extends Acc{public Cowhide() {System.out.println("这是牛皮坐垫");}
}public class Common extends Acc{public Common() {System.out.println("这是普通坐垫");}
}

抽象工厂

public interface AbstractFactory {//抽象工厂,定义创建具体工厂的规范Acc createAcc();Engine createEngine();
}

具体工厂

public class TeslaFactory implements AbstractFactory{//不同的具体产品根据自己的生产需求去创建不同的对象@Overridepublic Acc createAcc() {return new Cowhide();}@Overridepublic Engine createEngine() {return new V12Engine();}
}public class BMWFactory implements AbstractFactory{@Overridepublic Acc createAcc() {return new Common();}@Overridepublic Engine createEngine() {return new V8Engine();}
}

用户

public class Customer {public static void main(String[] args) {TeslaFactory teslaFactory = new TeslaFactory();teslaFactory.createEngine();teslaFactory.createAcc();System.out.println("————————————————————————");BMWFactory bmwFactory = new BMWFactory();bmwFactory.createAcc();bmwFactory.createEngine();}
}

 优缺点

当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象;

但是当产品组中需要增加一个新的产品时所有的工厂类都需要进行修改;

例如我如果想要再添加一个空调这个产品,不仅需要多一个空调的产品族,并且在抽象工厂中还需要添加一个创建空调的方法;

相关文章:

设计模式——工厂模式(简单工厂、工厂方法、抽象工厂)

是什么? 工厂模式的目的是将创建对象的具体过程隐藏起来,从而达到更高的灵活性 工厂模式分为:简单工厂模式、工厂方法模式、抽象工厂模式; 为什么? 在Java中,万物皆是对象,我们在使用的时候…...

《C语言技术体系》 学习路线总目录 + 思维导图

目录 前言 正文 思维导图 第1章 流程结构 1.1 初识C语言 1.2 流程结构 1.3 数据类型 1.4 运算符表达式 第2章 指针与数组 2.1 指针基本概念 2.2 一维数组 2.3 二维及多维数组 2.4 指针与数组 第3章 模块化重构 3.1 函数 3.2 typedef类型定义 3.3 enum枚举 3.…...

数字图像处理简答题

目录 1.人类视觉对颜色的主观感觉包括哪三类? 2. 图像成像的过程包括哪三步? 3.图像的采样和量化分别指什么? 4、取k8时,将下图用相应矩阵表示 5、简述当限定了数字图像的数据量时采样和量化参数的选择遵循哪两条原则&#x…...

【Java校招面试】基础知识(五)——GC

目录 前言一、基础概念二、垃圾回收算法三、垃圾收集器四、引用后记 前言 本篇主要介绍Java垃圾回收机制——GC的相关内容。 “基础知识”是本专栏的第一个部分,本篇博文是第五篇博文,如有需要,可: 点击这里,返回本专…...

使用CMake调用Makefile 项目

目录标题 基本示例Cmake传递lib给MakefileCmake传递参数给Makefile,比如make cleanWindows下使用Cmake调用Makefile 基本示例 如果项目是使用传统的Makefile构建的,并且您希望使用CMake调用这些Makefile,您可以使用CMake的add_custom_target…...

快速傅里叶变换FFT学习笔记

点值表示法 我们正常表示一个多项式的方式,形如 A ( x ) a 0 a 1 x a 2 x 2 . . . a n x n A(x)a_0a_1xa_2x^2...a_nx^n A(x)a0​a1​xa2​x2...an​xn,这是正常人容易看懂的,但是,我们还有一种表示法。 我们知道&#xf…...

如何下载安装驱动

1 打开浏览器 这里以Edge浏览器举例 第一步打开桌面上的Edge浏览器 如果您的桌面上没有 那么找到搜索栏 搜索Edge 然后打开 打开之后一般是这样 然后把我发送您的地址 驱动下载地址 https://t.lenovo.com.cn/yfeyfYyD (这个网址只是一个例子) 删除掉前…...

鸿蒙Hi3861学习四-Huawei LiteOS介绍

一、什么是LitesOS Huawei LiteOS是华为针对物联网领域推出的轻量级物联网操作系统,是华为物联网战略的重要组成部分,具备轻量级、低功耗、互联互通、组件丰富、快速开发等关键能力。基于物联网领域业务特征打造领域性技术栈,为开发者提供“一…...

Vue核心 收集表单数据 过滤器

1.14. 收集表单数据 收集表单数据: 若: ,则v-model收集的是value值,用户输入的就是value值。若: ,则v-model收集的是value值,且要给标签配置value值。若: 没有配置input的value属性,那么收集的就是checked(勾选 or 未…...

华为EC6108V9E/EC6108V9I_rk3228_安卓4.4.4_通刷_卡刷固件包

华为EC6108V9E/EC6108V9I_rk3228_安卓4.4.4_通刷_卡刷固件包-内有教程 特点: 1、适用于对应型号的电视盒子刷机; 2、开放原厂固件屏蔽的市场安装和u盘安装apk; 3、修改dns,三网通用; 4、大量精简内置的…...

数字化转型导师坚鹏:面向数字化转型的大数据顶层设计实践

面向数字化转型的大数据顶层设计实践 课程背景: 数字化背景下,很多企业存在以下问题: 不清楚大数据思维如何建立? 不清楚企业大数据分析方法? 不了解大数据应用成功案例? 课程特色: …...

day27_mysql

今日内容 零、 复习昨日 一、单表查询 二、多表联查 零、 复习昨日 1 DDL,DML,DQL是啥 DDL 数据定义语言(库,表,列)DML 数据操作语言(表内数据的操作增删改)DQL 数据查询语言(表内数据的查询&am…...

QwtPlotCurve使用说明

QwtPlotCurve是Qwt库中用于绘制曲线的类,可以在QwtPlot上绘制各种类型的曲线,如折线、样条线、散点等。以下是QwtPlotCurve的一些常用函数和使用说明: setSamples(const QPolygonF &samples):设置曲线的数据点,参数…...

JS逆向 -- 某平台登录加密分析

一、打开网站,使用账号密码登录 账号:aiyou123.com 密码:123456 二、通过F12抓包,抓到如下数据,发现密码加密了 三、加密结果是32位,首先考虑是md5加密。 四、全局搜索pwd,点击右上角&#xf…...

一分钟快速实现Flask框架的蓝图和视图

一分钟快速实现Flask框架的蓝图和视图 Flask是一个轻量级的Web应用框架,非常适合快速开发小型的Web应用。Flask框架使用蓝图(Blueprint)和视图(View)的概念来组织应用程序的代码。在本文中,我们将介绍如何…...

Mysql 约束练习【第13章_约束】

#第13章_约束 /* 基础知识 1.1 为什么需要约束? 为了保证数据的完整性! 1.2 什么叫约束?对表中字段的限制。 1.3 约束的分类: 角度1:约束的字段的个数 单列约束 vs 多列约束 角度2:约束的作用范围 列…...

java调用cmd命令

1.首先,我们需要了解一下 java是如何调用 cmd的: 6.在实际的开发中,我们有可能会遇到 java调用 cmd命令的情况: 7.对于一些特定的环境下,例如在嵌入式系统中,那么我们可以使用下面这种方式来调用 cmd命令&a…...

Qt音视频开发36-超时检测和自动重连的设计

一、前言 如果网络环境正常设备正常,视频监控系统一般都是按照正常运行下去,不会出现什么问题,但是实际情况会很不同,奇奇怪怪七七八八的问题都会出现,就比如网络出了问题都有很多情况(交换机故障、网线故障、带宽故障等),所以监控系统在运行过程中,还得做超时检测,…...

Reactor 第九篇 WebFlux重构个人中心,效果显著

1 重构背景 原有的开发人员早已离职,代码细节没人知道,经过了一段时间的维护,发现有以下问题: 个人中心系统的特征就是组装各个业务的接口,输出个人中心业务需要的数据,整个系统调用了几十个第三方业务线的…...

Vben Admin 自学记录 —— Drawer组件的基本使用及练习(持续更新中...)

Drawer 抽屉组件 对 antv 的 drawer 组件进行封装,扩展拖拽,全屏,自适应高度等功能。 Drawer相关使用及概念 练习 —— 在之前table基础上,添加查看功能,点击查看按钮,弹出抽屉显示单条表格数据&#xf…...

Android 9.0 根据包名默认授予app悬浮窗权限

1.概述 在9.0的设备开发中,对于在app中授予悬浮窗权限,也是通常用的功能,但在设备产品中预制app,需求要求默认授予悬浮窗权限, 就不需要在app中动态申请悬浮窗权限了,所以就来分析下这个实现这个功能 2.根据包名默认授予app悬浮窗权限的核心类 packages\apps\Settings\s…...

Swift中Data,String,[UInt8]的相互转换(6种互相转换)

var dataData() var array[UInt8]() var str"" //Data[UInt8] data.append(10) array[UInt8](data) print(array)//[10] //[UInt8]转Data array[1,2,3,4,5] dataData(array) print(data.count)//5 //Data转String data.removeAll() data.append(contentsOf:[0x31,…...

【微软Bing王炸更新】无需等待,人人可用,答案图文并茂,太牛了

🚀 AI破局先行者 🚀 🌲 AI工具、AI绘图、AI专栏 🍀 🌲 如果你想学到最前沿、最火爆的技术,赶快加入吧✨ 🌲 作者简介:硕风和炜,CSDN-Java领域优质创作者🏆&am…...

腾讯云的cdn怎么配置|腾讯云CDN配置教程

众所周知,WordPress系统不挂加速或者是服务器不好速度贼慢,所以要想办法解决访问速度的问题,经过我不断的研究腾讯云的CDN,因为我用的是zibll子比主题,不懂的就挂会导致无法使用第三方登录,因为有缓存导致一直不回调一直卡在那个登录界面和支付没反应要么出现二维码,要么…...

数据结构入门-顺序表链表

线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种实际中广泛使用多个数据结构,常见的线性表:顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构,也就说是连续的一条直线。…...

【AWS入门】AWS Lamda

目录 创建一个Lamda函数用Lamda函数控制启停EC2实例创建一台EC2实例创建角色创建lamda函数 使用Amazon EventBridge计划启停实例创建EventBridge 用户往S3存储桶上传图片文件,触发Lambda函数,将图片压缩并上传至另一个存储桶创建两个存储桶通过Cloudform…...

牛客刷SQL题Day5

SQL69 返回产品并且按照价格排序 select prod_name , prod_price from Products where prod_price between 3 and 6 select prod_name , prod_price from Products where 6>prod_price and prod_price >3 踩坑1: between......and.......包括边界。 踩坑2&am…...

【Errors】【计算机图形学】A-SDF复现的一点纠正记录

ICCV 2021的工作A-SDF,在跑的过程中可能是一些版我Run了这篇工作代码的Reconstruction,然后出现了一点小小的错误,记录如下。 问题一:对数据做直接修改导致出错(可能是不同的pytorch版本导致的?) 错误描述…...

Dockerfile创建镜像文件

Dockerfile Docker镜像原理 Linux文件系统有bootfs和rootfs两部分组成 Docker镜像由特殊文件系统叠加 最底端bootfs,使用宿主机bootfs 第二次时rootfs,被称为基础镜像 向上可以叠加其他镜像文件 同一文件系统能将多层整合成一层,隐藏了多层存在 镜像可以放置…...

javascript中的严格模式

认识严格模式: 在ECMAScript5标准中,JavaScript提出了严格模式的概念(Strict Mode): 严格模式很好理解,是一种具有限制性的JavaScript模式,从而是代码隐式的脱离了“懒散(sloppy)模…...

拱墅网站建设制作/seo网站自动发布外链工具

2.2 单页面应用介绍 什么是单页应用?引用百度百科:单页面应用的优缺点:优点:1、用户操作体验好,用户不用刷新页面,整个交互过程都是通过Ajax来操作。 2、适合前后端分离开发,服务端提供http接口…...

网站推广优化外包/google关键词搜索工具

1.java中有自带的方法Math类中round,可以自己查看API。 API中是这么介绍的:round(double a) 返回参数中最接近的 long ,其中 long四舍五入为正无穷大。 Eg: double a10;double b3.0;double c;ca/b;System.out.println(c); 上面的结果是&…...

网站建设公司做销售前景好不好?/广州信息流推广公司

前言 大家好,今天给大家讲一讲Python的综合实战演练内容——以大众都非常喜爱的火锅为例,如何用我们掌握的Python语言,去获取全国不同城市火锅店数量情况,并将这些数据进行可视化展示呢? 接下来我将带大家实现这一操…...

日本网站欣赏/宁海关键词优化怎么优化

一、需求:有这么一张表前四个属性当作联合主键需要把该表所有的行在前端以表格形式显示出来,要求activityId相同时合并成一行,activityCode相同时,合并一行,activityVersion相同时也合并一行。类似这种:二、…...

为了爱我可以做任何事俄剧网站/官网seo

一套完整的WordPress模板应至少具有如下文件: style.css : CSS(样式表)文件index.php : 主页模板archive.php : Archive/Category模板404.php : Not Found 错误页模板comments.php : 留言/回复模板footer.php : Footer模板header.php : Header模板sidebar.php : 侧栏…...

做网站正规公司/优化关键词软件

1,直接在当前浏览器更换皮肤 2,在当前浏览器更换皮肤并保存到cookle 3,在当前浏览器更换皮肤并保持到config文件 1.直接添加其他css文件换肤. 皮肤文件:xtheme-olive.zip下载 把皮肤文件解压,把css文件(如xtheme-olive.css…...