工厂模式并不难理解

文章目录

  • 工厂模式
    • 简单工厂模式
      • 简单工厂模式使用的场景
    • 工厂方法模式
      • 工厂方法模式使用场景
    • 抽象工厂模式
      • 抽象工厂模式使用场景

工厂模式

功能:将对象的创建交给工厂,我们只需要告诉工厂我们要什么对象就可以得到该对象。

目的:实现创建对象和使用对象分离;让我们更加关注需要什么,而不是这个是怎么来的。

工厂模式根据不同的创建场景和创建需求可以分为:简单工厂、工厂方法、抽象工厂

例如:现在需要制造汽车,汽车有不同的颜色,将不同的颜色分成类。

将汽车抽象为一个Car抽象类,不同颜色的汽车分别继承它。

public abstract class Car {String color;public  abstract  void carColor();public  void carSpeed(){System.out.println(String.format("正在生产%s的汽车,时速100KM/h",color));}public  void carPrice(){System.out.println(String.format("正在生产%s的汽车,价格10W",color));}
}
public class BlackCar extends  Car {public BlackCar() {this.color = "黑色";}@Overridepublic void carColor() {System.out.println(String.format("生产的是%s的车",color));}
}
public class PinkCar extends Car {public PinkCar() {this.color = "粉色";}@Overridepublic void carColor() {System.out.println(String.format("生产的是%s的车",color));}
}

在最开始我们要创建什么汽车就会手动的new对应的汽车,

简单工厂模式

简单工厂不是一种设计模式,它是为接下来的工厂方法模式提供基础的。

通过简单工厂模式会创建如下的一个工厂:

public class SimpleFactory {public Car creatCar(String color){if ("pink".equals(color)){return new PinkCar();}else if("black".equals(color)){return new BlackCar();}else {System.out.println("无法制造"+color+"颜色的车");return null;}}
}

测试代码:

public class Test {public static void main(String[] args) {SimpleFactory factory = new SimpleFactory();Car pink = factory.creatCar("pink");pink.carColor();pink.carPrice();pink.carSpeed();}
}/*
生产的是粉色的车
正在生产粉色的汽车,价格10W
正在生产粉色的汽车,时速100KM/h
*/

类图如下:

在这里插入图片描述

用标识符“pink”传递非常容易出错,我们可以使用java提供的反射,此时简单工厂变为:

public class SimpleFactory {public Car creatCar(Class<? extends Car> clazz){try {return  clazz.newInstance();} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}}
}

测试代码变为:

public class Test {public static void main(String[] args) {SimpleFactory factory = new SimpleFactory();Car pink = factory.creatCar(PinkCar.class);pink.carColor();pink.carPrice();pink.carSpeed();}
}

类图如下:用户之和工厂之间有联系,而和具体的汽车类是没有联系的。

在这里插入图片描述

简单工厂模式使用的场景

工厂负责创建的对象较少。

客户端只需要出入一个工厂类的参数,对于内部的逻辑不用关心。

优点:只需要插入一个正确的参数,无需在意细节。

缺点:工厂类的职责相对较重,新增产品时需要修改工厂的逻辑,违背开闭原则。不宜扩展过于复杂的产品结构。

工厂方法模式

简单工厂模式中,一旦需要大规模的添加新的创建对象时需要修改工厂的逻辑,违背开闭原则,不方便使用。

工厂方法模式与简单工厂模式不同的是:方法工厂模式会为每一个类创建一个工厂,用的时候就会创建自己对应的工厂,通过对应的工厂创建对象;再创建一个总工厂,就是对工厂的抽象。

三个汽车类不变,

创建对应的工厂类

public abstract class CarFactory {abstract Car creatCar();
}
public class PinkCarFactory extends CarFactory{@OverrideCar creatCar() {System.out.println("正在生产粉色汽车");return new PinkCar();}
}
public class BlackCarFactory extends CarFactory {@OverrideCar creatCar() {System.out.println("正在生产黑色汽车");return new BlackCar();}
}

测试:

public static void main(String[] args) {CarFactory  carFactory = null ;Scanner scanner = new Scanner(System.in);System.out.println("请输入您想要生产的汽车颜色");String s = scanner.next();if(s.equals("black")){carFactory = new BlackCarFactory();}else if(s.equals("pink")){carFactory = new PinkCarFactory();}else {System.out.println("没有这类颜色的车");}carFactory.creatCar();}

在这里插入图片描述

工厂方法模式使用场景

创建对象需要大量重复的代码。

优点

产品只需要要关心对应的工厂,无需关心创建细节。

加入新的产品时符合开闭原则,提高系统的可扩展性。

缺点

类的数量过多,增加了代码结构的复杂度。

增加了系统的抽象性和理解难度。

抽象工厂模式

是为访问类提供一个创建一系列相关或相互依赖对象的接口,无需指定他们具体的类,就能得到同族的不同等级的产品。

什么意思呢?

在这里插入图片描述

利用B站视屏的例子:
在这里插入图片描述

左图中商务一套搭配属于同一族,右边运动服属于一族,右边的外套和左边的外套属于不同组的同一个等级,右图中的上衣,裤子,鞋是同族的不同等级产品。

以上提到的只是汽车的颜色不同,例如,无论什么颜色的车都有七座和五座两种。

结构

  • 抽象工厂:提供创建产品的接口,包含多个创建产品的方法,可以创建多个不同等级的产品。
  • 具体工厂:主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
  • 抽象产品:定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
  • 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。

还是上面那个汽车案例,要求:黑色汽车安装A类引擎,粉色汽车安装B类引擎。则黑色汽车和A类引擎是同一族,粉色汽车和黑色汽车是同一等级。

具体实现:

具体产品和抽象产品:

public abstract class Car {String color;public  abstract  void carColor();
}
public class BlackCar extends Car  {public BlackCar() {this.color = "黑色";}@Overridepublic void carColor() {System.out.println(String.format("生产的是%s的车", color));}
}
public class PinkCar extends Car  {public PinkCar() {this.color = "粉色";}@Overridepublic void carColor() {System.out.println(String.format("生产的是%s的车", color));}
}
public abstract class Engine {abstract void getEngine();
}
public class EngineA extends Engine{@Overridevoid getEngine() {System.out.println("引擎A");}
}
public class EngineB extends Engine{@Overridevoid getEngine() {System.out.println("引擎B");}
}

具体工厂和抽象工厂:

public abstract interface CarFactory {//生产汽车Car creatCar();//生产引擎Engine creatEngine();
}
public class BlackFactory implements   CarFactory{@Overridepublic Car creatCar() {return new BlackCar();}@Overridepublic Engine creatEngine() {return new EngineA();}
}
public class PinkCarFactory implements CarFactory {@Overridepublic Car creatCar() {return new PinkCar();}@Overridepublic Engine creatEngine() {return new EngineB();}
}

test:

public class Test {public static void main(String[] args) {BlackFactory blackFactory = new BlackFactory();Car car = blackFactory.creatCar();Engine engine = blackFactory.creatEngine();car.carColor();engine.getEngine();PinkCarFactory pinkCarFactory = new PinkCarFactory();Car car1 = pinkCarFactory.creatCar();Engine engine1 = pinkCarFactory.creatEngine();car1.carColor();engine1.getEngine();}
}
/*
生产的是黑色的车
引擎A
生产的是粉色的车
引擎B
*/

如果要加入同一个产品族的话,只需要再加一个对应的工厂类即可,不需要修改其他产品族的对象。

抽象工厂模式使用场景

  • 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机,洗衣机,空调等。
  • 系统中有多个产品族,但每次使用其中的某一族产品。如有人只喜欢某一个品牌的衣服和鞋。
  • 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖具体实现。

优点:当产品族中多个对象被设计成在一起工作时,他能保证客户端始终只使用同一个产品族中的对象。(固定搭配)

缺点:如果要在产品族中添加一个产品的话,所有的工厂类都需要改动。

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

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

相关文章

【算法刷题之链表篇(1)】

目录 1.leetcode-82. 删除排序链表中的重复元素 II&#xff08;1&#xff09;题目描述&#xff08;2&#xff09;方法及思路&#xff08;一次遍历&#xff09;&#xff08;3&#xff09;代码实现 2.leetcode-19. 删除链表的倒数第 N 个结点&#xff08;1&#xff09;题目描述&a…

无需公网IP——搭建web站点

文章目录 概述使用 Raspberry Pi Imager 安装 Raspberry Pi OS设置 Apache Web 服务器测试 web 站点安装静态样例站点将web站点发布到公网安装 Cpolar内网穿透cpolar进行token认证生成cpolar随机域名网址生成cpolar二级子域名将参数保存到cpolar配置文件中测试修改后配置文件配…

认识容器,走进Docker

文章目录 容器技术简介容器的核心技术容器平台技术容器的支持技术 Docker理念Docker安装配置阿里云镜像加速器 容器技术简介 一切在云端&#xff0c;万物皆容器&#xff0c;说到容器&#xff0c;大家都会想到Docker,Docker现在几乎是容器的代名词&#xff0c;什么是Docker&…

网络通信原理TCP的四次断开连接(第四十九课)

FIN:发端完成发送任务标识。用来释放一个连接。FIN=1表明此报文段的发送端的数据已经发送完毕,并要求释放连接。 SEQ:序号字段。 TCP链接中传输的数据流中每个字节都编上一个序号。序号字段的值指的是本报文段所发送的数据的第一个字节的序号。 序列号为X ACK :确认号 。 …

ViT模型架构和CNN区别

目录 Vision Transformer如何工作 ViT模型架构 ViT工作原理解析 步骤1&#xff1a;将图片转换成patches序列 步骤2&#xff1a;将patches铺平 步骤3&#xff1a;添加Position embedding 步骤4&#xff1a;添加class token 步骤5&#xff1a;输入Transformer Encoder 步…

【Rust】Rust学习 第十五章智能指针

指针 &#xff08;pointer&#xff09;是一个包含内存地址的变量的通用概念。这个地址引用&#xff0c;或 “指向”&#xff08;points at&#xff09;一些其他数据。Rust 中最常见的指针是第四章介绍的 引用&#xff08;reference&#xff09;。引用以 & 符号为标志并借用…

C# Linq源码分析之Take (三)

概要 本文在前两篇Take源码分析的基础上&#xff0c;着重分析Range参数中有倒数的情况&#xff0c;即分析TakeRangeFromEndIterator的源码实现。 源码及分析 TakeRangeFromEndIterator方法用于处理Range中的开始和结束索引存在倒数的情况。该方法位于Take.cs文件中。通过yie…

Lnton羚通算法算力云平台在环境配置时 OpenCV 无法显示图像是什么原因?

问题&#xff1a; cv2.imshow 显示图像时报错&#xff0c;无法显示图像 0%| | 0/1 [00:00<…

构建 NodeJS 影院微服务并使用 docker 部署【01/4】

图片来自谷歌 — 封面由我制作 一、说明 构建一个微服务的电影网站&#xff0c;需要Docker、NodeJS、MongoDB&#xff0c;这样的案例您见过吗&#xff1f;如果对此有兴趣&#xff0c;您就继续往下看吧。 在本系列中&#xff0c;我们将构建一个 NodeJS 微服务&#xff0c;并使用…

qt初入门0:结构体中QString用memset导致崩溃分析及QLatin1String简单查看源码

初识Qt,进行开发时遇到一个崩溃问题 简单整理 1&#xff1a;问题描述如下&#xff0c;结构体中QString成员&#xff0c;然后对结构体调用了memset导致问题&#xff1a; 2&#xff1a;问题分析&#xff0c;加断点调试的方式可以明确分析到行数 可以明确看出&#xff0c;初始化…

Windows下问题定位

1、内存相关知识点&#xff1b; 1&#xff09;windows下32位进程&#xff0c;用户态为2G内存&#xff0c;内核态也为2G内存&#xff1b;却别于linux操作系统&#xff1b; 备注&#xff1a;可以通过命令行与管理员权限&#xff0c;启动3G的用户态空间&#xff0c;但是部…

git权限问题解决方法Access denied fatal: Authentication failed

文章目录 遇到Access denied 的权限问题解决方法1、git的密码修改过&#xff0c;但是本地没更新。2、确定问题&#xff0c;然后增加配置① 查询用户信息②如果名称和email不对&#xff0c;设置名称&#xff1a;③ 检查ssh-add是否链接正常④ 设置不要每次都输入用户名密码 3、配…

【校招VIP】CSS校招考点之选择器优先级

考点介绍&#xff1a; 选择器是CSS的基础&#xff0c;也是校招中的高频考点&#xff0c;特别是复合选择器的执行优先级&#xff0c;同时也是实战中样式不生效的跟踪依据。 因为选择器的种类较多&#xff0c;很难直接记忆&#xff0c;可以考虑选择一个相对值&#xff0c;比如id类…

人大进仓数据库ksql命令基础

测试环境信息: 系统为银河麒麟V10 数据库为Kingbase ES V8 数据库安装目录为/opt/Kingbase/ES/V8 ksql命令位于/opt/Kingbase/ES/V8/Server/bin下 使用--help获取帮助 续上图 1.查看数据库列表 ./ksql -U system -l 2.查看数据库版本 ./ksql -V 3.连接指定的数据库tes…

【GAMES202】Real-Time Shadows2—实时阴影2

一、PCSS回顾 上一篇我们说了如何用PCSS是实现软阴影&#xff0c;这个过程是没有任何问题的&#xff0c;但是有一个速度的问题&#xff0c;因为PCSS涉及到非常多次对纹理特定某一块区域遍历的操作&#xff08;工业界一般都是用在该区域采样的方式&#xff0c;会因此产生噪声&am…

Zookeeper集群单节点启动成功但未同步其他节点数据

首先排查节点启动是否正常&#xff1a; 在zookeeper的bin目录下执行&#xff1a;sh zkServer.sh status 判断当前节点数据leader 还是follower 节点都启动正常&#xff0c;但某一个zookeeper集群节点&#xff08;下面简称“异常节点”&#xff09;不同步其他节点数据&#xf…

SQL-每日一题【1321. 餐馆营业额变化增长】

题目 表: Customer 你是餐馆的老板&#xff0c;现在你想分析一下可能的营业额变化增长&#xff08;每天至少有一位顾客&#xff09;。 计算以 7 天&#xff08;某日期 该日期前的 6 天&#xff09;为一个时间段的顾客消费平均值。average_amount 要 保留两位小数。 结果按 …

最新两年工作经验总结

最新两年工作经验总结 前言URP的使用1&#xff1a;如何开启URP1、老项目升级为URP2、创建新项目时选择URP创建 2&#xff1a;URP阴影的设置 PolyBrush的使用&#xff08;地图编辑插件&#xff09;制作山峰or低谷边缘柔化雨刷上色制造场景中的物体贴图地形创建容易踩坑的点ProBu…

java 工程管理系统源码+项目说明+功能描述+前后端分离 + 二次开发 em

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显…

【C++习题集】-- 堆

&#xff08;用于复习&#xff09; 目录 树概念及结构 名词概念 二叉树概念及结构 特殊的二叉树 满二叉树 完全二叉树 运算性质 二叉树存储结构 顺序存储 链式存储 堆 - 顺序存储 堆的性质 堆的实现 堆的应用 堆排序 直接建堆法 树概念及结构 概念&#xff1a…