设计模式-三种工厂模式的优缺点和使用场景

news2024/10/7 7:26:20

本文参考:

常见设计模式解析,应用场景以及优点(一)单例,工厂,抽象工厂,构造者_口怪物口的博客-CSDN博客_简述常见的工厂模式以及单例模式的使用场景

轻松理解工厂模式!就等面试官问了!_牛客网 (nowcoder.com)

工厂模式

工厂模式(Factory Pattern) 是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

简单工厂模式

简单工厂模式只是将不同对象的创建操作进行了一层简单的封装,其实也就是把不同对象的创建操作全都单独放到一个类中,这个类就成为了简单工厂类。

  • 实现一个电脑工厂,由电脑工厂根据需求生成不同品牌的电脑。
  1. 创建一个电脑抽象类

    public abstract class Computer {
        public abstract void use();
    }
    
  2. 创建抽象类的具体实现类,两款电脑

    public class AppleComputer extends Computer{
        public AppleComputer(){
            System.out.println("生产了Apple电脑...");
        }
        @Override
        public void use() {
            System.out.println("使用了Apple电脑...");
        }
    }
    
    public class LenoveComputer extends Computer{
        public LenoveComputer(){
            System.out.println("生产了Lenove电脑...");
        }
        @Override
        public void use() {
            System.out.println("使用了Lenove电脑...");
        }
    
    }
    
  3. 创建一个电脑工厂

    public class SimpleComputerFactory {
        public static Computer produceComputer(String brand){
            if(brand==null){
                return null;
            }
            if(brand.equalsIgnoreCase("Apple")){
                return new AppleComputer();
            }else if(brand.equalsIgnoreCase("Lenove")){
                return new LenoveComputer();
            }
            return null;
        }
    }
    
  4. 测试

    public class SimpleFactoryTest {
        public static void main(String[] args) {
            SimpleComputerFactory computerFactory = new SimpleComputerFactory();
            Computer lenove = computerFactory.produceComputer("Lenove");
            lenove.use();
            Computer apple = computerFactory.produceComputer("Apple");
            apple.use();
        }
    }
    

在这里插入图片描述

优点:简单工厂模式可以根据需求,动态生成使用者所需类的对象,而使用者不用去知道怎么创建对象,使得各个模块各司其职,降低了系统的耦合性

缺点:拓展性差,违背了开闭原则,由于只有一个工厂类,新增产品时,需要修改这个工厂类。

应用场景:调用方不用担心具体实例化,只需要关心有没有自己想要获取的类,工厂内部通过字符串进行判断返回,将创建实例和使用实例的工作分开。

工厂方法模式

简单工厂模式只有一个总工厂,工厂方法模式额外定义了一个抽象总工厂,在总工厂类下还有许多子工厂,不同的对象由其对应的子工厂进行创建。与简单工厂模式对比起来,一个商品需要创建一个额外的工厂类,这样子当我们需要扩展一个新产品时,只需要拓展一个工厂类就行,不用修改总工厂的代码,满足了开闭原则。

  • 实现一个电脑工厂,再根据不同品牌实现电脑工厂子类,由电脑工厂子类根据需求生成不同品牌的同一类型的电脑。
  1. 创建一个电脑抽象类

    public abstract class Computer {
        public abstract void use();
    }
    
  2. 创建抽象类的具体实现类,两款电脑

    public class AppleComputer extends Computer{
        public AppleComputer(){
            System.out.println("生产了Apple电脑...");
        }
        @Override
        public void use() {
            System.out.println("使用了Apple电脑...");
        }
    }
    
    public class LenoveComputer extends Computer{
        public LenoveComputer(){
            System.out.println("生产了Lenove电脑...");
        }
        @Override
        public void use() {
            System.out.println("使用了Lenove电脑...");
        }
    
    }
    
  3. 创建一个抽象电脑总工厂,里面有一个produce()生产的抽象方法

    public abstract class MethodFactory {
        public abstract Computer produce();
    }
    
  4. 创建产品各自的分工厂

    public class AppleComputerFactory extends MethodFactory{
        @Override
        public Computer produce() {
            return new AppleComputer();
        }
    }
    
    public class LenoveComputerFactory extends MethodFactory{
        @Override
        public Computer produce() {
            return new LenoveComputer();
        }
    }
    
  5. 测试

    public class SimpleFactoryTest {
        public static void main(String[] args) {
            SimpleComputerFactory computerFactory = new SimpleComputerFactory();
            Computer lenove = computerFactory.produceComputer("Lenove");
            lenove.use();
            Computer apple = computerFactory.produceComputer("Apple");
            apple.use();
        }
    }
    

在这里插入图片描述

优点:扩展性好,符合了开闭原则,新增一种产品时,只需增加改对应的产品类和对应的工厂子类即可。比如样例实现中,当我们需要一个苹果电脑时,只需要去新增一个苹果电脑类和一个苹果工厂类即可,而无需去修改原有的代码。符合单一职责原则,每个工厂只负责一种产品,而不是由一个工厂去生成所有商品。

缺点: 当我们新增产品时,还需要提供对应的工厂类,系统中类的个数将会成倍增加,相当于增加了系统的复杂性。

使用场景:将创建实例和使用实例的工作分开,低耦合性地创建类,同时符合开闭原则。

抽象工厂模式

抽象工厂模式有点像是工厂方法模式的升级版。

工厂方法模式生产的是同一品牌的一种类型的商品,而抽象工厂模式可以生产同一品牌不同类型的商品。相当于是抽象电脑总工厂里面的抽象方法变多了,同一子工厂生产的类型也多了。

实现一个电脑工厂,再根据不同品牌实现电脑工厂子类,由电脑工厂子类根据需求生成不同品牌的不同类型的电脑。

  1. 创建不同类型的电脑抽象类

    public abstract class DesktopComputer {
        public abstract void use();
    }
    
    public abstract class NotebookComputer {
        public abstract void use();
    }
    
  2. 创建抽象类的具体实现类,两种品牌的电脑,每种电脑各有两种类型

    public class AppleDesktopComputer extends DesktopComputer{
        public AppleDesktopComputer(){
            System.out.println("生产了Apple的台式电脑...");
        }
        @Override
        public void use() {
            System.out.println("使用了Apple的台式电脑...");
        }
    }
    
    public class AppleNotebookComputer extends NotebookComputer{
        public AppleNotebookComputer(){
            System.out.println("生产了Apple的笔记本电脑...");
        }
        public void use() {
            System.out.println("使用了Apple的笔记本电脑...");
        }
    }
    
    public class LenoveDesktopComputer extends DesktopComputer{
        public LenoveDesktopComputer(){
            System.out.println("生产了Lenove的台式电脑...");
        }
        @Override
        public void use() {
            System.out.println("使用了Lenove的台式电脑...");
        }
    }
    
    public class LenoveNotebookComputer extends NotebookComputer{
        public LenoveNotebookComputer(){
            System.out.println("生产了Lenove的笔记本电脑...");
        }
        public void use() {
            System.out.println("使用了Lenove的笔记本电脑...");
        }
    }
    
  3. 创建生产不同类型电脑的总工厂抽象类

    public class AppleFactory extends AbstractFactory{
    
        public DesktopComputer produceDesktopComputer() {
            return new AppleDesktopComputer();
        }
    
        public NotebookComputer produceNotebookComputer() {
            return new AppleNotebookComputer();
        }
    }
    
    public class LenoveFactory extends AbstractFactory{
    
        public DesktopComputer produceDesktopComputer() {
            return new LenoveDesktopComputer();
        }
    
        public NotebookComputer produceNotebookComputer() {
            return new LenoveNotebookComputer();
        }
    }
    
  4. 测试

    public class AbstractFactoryTest {
        public static void main(String[] args) {
            AppleFactory appleFactory = new AppleFactory();
            DesktopComputer appleDesktopComputer = appleFactory.produceDesktopComputer();
            appleDesktopComputer.use();
            NotebookComputer appleNotebookComputer = appleFactory.produceNotebookComputer();
            appleNotebookComputer.use();
    
            LenoveFactory lenoveFactory = new LenoveFactory();
            DesktopComputer lenoveDesktopComputer = lenoveFactory.produceDesktopComputer();
            lenoveDesktopComputer.use();
            NotebookComputer lenoveNotebookComputer = lenoveFactory.produceNotebookComputer();
            lenoveNotebookComputer.use();
        }
    }
    

在这里插入图片描述

优点:工厂总抽象类可以创建多个类型的产品,当有需求时,可以创建相关产品子类和子工厂类来获取。也就是可以满足生产不同品牌的不同类型的电脑。

缺点: 扩展新种类产品时困难。抽象工厂模式需要我们在工厂抽象类中提前确定了可能需要的产品种类,以满足不同品牌的多种产品的需求。但是如果我们需要的产品种类并没有在工厂抽象类中提前确定,那我们就需要去修改工厂抽象类了,而一旦修改了工厂抽象类,那么所有的工厂子类也需要修改,这样显然扩展不方便。

使用场景:适用于提供的某实例或某些相关联的实例种类较多的情况,或者是该实例创建方式灵活扩展的可能性较大的情况.将创建实例和使用实例的工作分开,如JUC中线程池创建新线程的方式是多样话的并且是可扩展的,就是用ThreadFactory可扩展接口来实现

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

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

相关文章

4.29补题记录

昨天做了俩道补题,感觉很自己有点无脑了 一、镜像最短距离 思路 首先这道题我最开始想的是bfs记录步数来做的,当时测试的时候没写出来,后来,看补题的时候,才发现这个就是简单的数学问题,我们只要计算出初…

项目管理软件可以用来做什么?这篇文章说清楚了

项目管理软件是用来干嘛的,就得看对项目的理解。项目是为创造独特的产品、服务或成果而进行的临时性工作。建造一座大楼可以是一个项目,进行一次旅游活动、日常办公活动、期末考试复习等也都可以看成一个项目。 项目管理不善会导致项目超时、超支、返工、…

javascript-算法基础-01

时间复杂度 O(1) O(n) O(n) O(2ⁿ) 记得有次面试, 让我求1 … n, 我说用for循环. 当时竟然都忘了等差数列公式了… 一个简单的求和 let res 0 // 1 for(let i; i < arr.length; i){ // 1res arr[i] // n }let res 0 for(const …

肝一肝设计模式【四】-- 建造者模式

系列文章目录 肝一肝设计模式【一】-- 单例模式 传送门 肝一肝设计模式【二】-- 工厂模式 传送门 肝一肝设计模式【三】-- 原型模式 传送门 肝一肝设计模式【四】-- 建造者模式 传送门 文章目录 系列文章目录前言一、什么是建造者模式二、举个栗子三、静态内部类写法四、开源框…

Golang-常见数据结构Map

Map map 是一种特殊的数据结构&#xff1a;一种元素对&#xff08;pair&#xff09;的无序集合&#xff0c;pair 的一个元素是 key&#xff0c;对应的另一个元素是 value&#xff0c;所以这个结构也称为关联数组或字典。这是一种快速寻找值的理想结构&#xff1a;给定 key&…

5 款 AI 老照片修复工具的横向比较

在大语言模型和各类 AI 应用日新月异的今天&#xff0c;我终于下定决心&#xff0c;趁着老照片们还没有完全发黄褪色、受潮粘连抑或损坏遗失&#xff0c;将上一代人实体相册里的纸质胶卷照片全部数字化&#xff0c;并进行一次彻底的 AI 修复&#xff0c;好让这些珍贵的记忆能更…

宽带IPTV单线复用

宽带IPTV单线复用 中国联通类&#xff1a; 1、前言 为了解决家里电视墙只预留了一个网口&#xff0c;IPTV无法与路由器共存的问题。 网络环境&#xff1a;中国联通 作者使用的路由器&#xff1a;云易家AX18C 2、光猫获取超管密码 黑龙江&#xff1a;hljcuadmin 重庆&…

HTML基础 + 实例解析

我们的目标: 认识HTML语言学会常用的HTML标签 目录 HTML的框架结构 HTML常见标签使用 1.注释标签 2. 标题标签 3. 段落标签 4. 换行标签 5. 格式化标签 6. 图片标签 7. 超链接标签 8. 表格标签 9. 表格标签-单元格合并 10. 列表标签 无序列表标签 有序标签 11. 表单标签 inp…

将 Quicker 搜索功能打造成专属于你的 Windows 启动器

在 macOS 平台上&#xff0c;有许多优秀的启动器&#xff0c;如老牌双雄 Alfred、Launchbar 和新秀 Raycast。反观 Windows 平台&#xff0c;则有 uTools、Listary、Wox 等应用&#xff0c;它们在基础功能上表现不错&#xff0c;但受限于应用生态&#xff0c;可拓展性都较弱。Q…

Java——Java面向对象

该系列博文会告诉你如何从入门到进阶&#xff0c;一步步地学习Java基础知识&#xff0c;并上手进行实战&#xff0c;接着了解每个Java知识点背后的实现原理&#xff0c;更完整地了解整个Java技术体系&#xff0c;形成自己的知识框架。 概述&#xff1a; Java是面向对象的程序…

【C++】类与对象(1)

【C】类与对象&#xff08;1&#xff09; 作者&#xff1a;爱写代码的刚子 时间&#xff1a;2023.4.29 本篇博客是有关C类与对象的知识&#xff0c;学习了类与对象就相当于一只脚踏进了C的大门&#xff0c;本篇博客会深入讲解C中的类与对象&#xff08;重点为this指针&#xff…

C++知识点 -- 异常

C知识点 – 异常 文章目录 C知识点 -- 异常一、异常概念二、异常的使用1.异常的抛出和捕获2.异常的重新抛出3.异常安全4.异常规范 三、自定义异常体系四、C标准库的异常体系五、C异常的优缺点 一、异常概念 当一个函数发现自己无法处理错误时&#xff0c;就可以抛出异常&#…

Python超矩形

文章目录 距离函数矩形分割 Rectangle是 scipy.spatial中封装的类&#xff0c;其构造函数只需输入最小值和最大值的数组即可&#xff0c;并且可通过内置的 volume方法计算广义的体积。 from scipy.spatial import Rectanglerec Rectangle((0,0), (5,5)) print(rec.maxes) …

java-会话技术

1.1 会话管理概述 1.1.1 什么是会话 这里的会话&#xff0c;指的是web开发中的一次通话过程&#xff0c;当打开浏览器&#xff0c;访问网站地址后&#xff0c;会话开始&#xff0c;当关闭浏览器&#xff08;或者到了过期时间&#xff09;&#xff0c;会话结束。 举个例子&am…

py_rabbitmq

安装 服务端 https://www.jianshu.com/p/2fb6d5ac17b9 客户端 pip install pika文档 https://rabbitmq.com/tutorials/tutorial-one-python.html 简单示例 生产者 import pika import rabbitmq_study.settings as settingscredentials pika.PlainCredentials(settings…

Python每日一练(20230430)

目录 1. 移除元素 &#x1f31f; 2. 删除排序链表中的重复元素 &#x1f31f; 3. 搜索旋转排序数组 II &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1.…

总结836

学习目标&#xff1a; 4月&#xff08;复习完高数18讲内容&#xff0c;背诵21篇短文&#xff0c;熟词僻义300词基础词&#xff09; 学习内容&#xff1a; 暴力英语&#xff1a;背诵《keep your direction》&#xff0c;默写&#xff0c;英语语法 高等数学&#xff1a;刷题&a…

node笔记_安装nvm管理node版本

文章目录 前言下载nvm安装nvmnvm路径node路径查看版本nvm -v查看nvm的node版本列表&#xff08;nvm list available&#xff09;配置nvm的镜像库mirror选择node版本安装 (node install version)使用指定的node版本&#xff08;nvm use&#xff09; node环境变量配置配置NODE_PA…

【打卡】图像检索与匹配4 孪生网络

任务4&#xff1a;孪生网络 孪生网络是一种由两个相同结构的神经网络组成的模型&#xff0c;其目的是将两个输入数据映射到一个共同的向量空间中&#xff0c;并计算它们之间的相似度或距离。它通常用于图像匹配、人脸识别、语义匹配等任务中。 步骤1&#xff1a;构建三元组数…

MIT 6.824 lab4A总结

Background 一个raft集群的性能很明显和raft的数量有关系&#xff0c;更重要的是如果我们多个key放在一个raft集群里&#xff0c;这样的并行性不太好。所以我们可以考虑分片&#xff0c;利用操作潜在的并行性来提升性能。每一个副本组只管理几个分片的put和get&#xff0c;并且…