工厂模式白话 - 3种都有哦

前言

工厂模式(Factory Pattern)里所谓的“工厂”和现实生活中的工厂一样

主要作用都是生产产品

像食品厂、服装厂、汽车厂生产吃的、穿的、开的

设计模式里的工厂则是生产对象

划分

工厂模式可分为简单工厂、工厂方法、抽象工厂3种

有啥不同呢?

以汽车品牌举例,有别克、凯迪拉克、比亚里、特斯拉等等

1 简单工厂模式

好比一个能生产任何品牌的轿车工厂(一个轿车工厂,能生产别克、凯迪拉克、比亚迪、特斯拉,简直不要太强大)

关键实现 ①工厂类提供工厂方法;②工厂方法接收参数;③通过参数实例化不同的产品

1.1 代码实现

既然是一个 method + param 就能实例化出不同的对象

那就需要用到 OOP 的多态

先定义一个轿车对象的ICar接口(造出来的轿车能启动、能跑)

// 轿车
public interface ICar {
    void start();
    void run();
}
复制代码

实现ICar接口(别克轿车、凯迪拉克轿车)

public class BuickCar implements ICar {  
    @Override  
    public void start() {  
        System.out.println("别克轿车启动");  
    }
    @Override  
    public void run() {  
        System.out.println("别克轿车定速巡航");  
    }  
}

public class CadillacCar implements ICar {  
    // 很简单,不写了 
}
复制代码

然后声明一个轿车工厂(工厂类)并定义造车方法(工厂方法)

public class CarFactory {  
    public ICar buildCar(String carName) {  
        ICar car = null;  
        if ("别克".equals(carName)) {  
            car = new BuickCar();  
        } else if ("凯迪拉克".equals(carName)) {  
            car = new CadillacCar();  
        }  
        return car;  
    }  
}
复制代码

OK。分别造一辆别克、一辆凯迪拉克的轿车

public class SimpleFactoryDemo {
    public static void main(String[] args) {
        // 造一辆别克轿车
        CarFactory carFactory = new CarFactory();
        ICar buickCar = carFactory.buildCar("别克");
        buickCar.start();
        buickCar.run();
        
        // 造一辆凯迪拉克轿车
        ICar cadillacCar = carFactory.buildCar("凯迪拉克");
        cadillacCar.start();
        cadillacCar.run();
    }
}
复制代码

1.2 优缺点

它的优点就是够简单

至于缺点

比如这个简单工厂太牛了,还能造奔驰、宝马、奥迪等等100多个品牌的轿车

那么使用简单工厂模式会有2个问题:

  1. 工厂类中代码过多:CarFactory 里 buildCar()需要加上100多个 if...else,看着就头疼
  2. 违反开闭原则:改buildCar()时要是手抖误触,凯迪拉克变成凯迪克,那原来的凯迪拉克就造不出来了

可见,简单工厂模式不适用于有很多子产品的场景

2 工厂方法模式

好比简单工厂的专精版本,改用多个工厂、每个工厂生产自己品牌的轿车(别克工厂、凯迪拉克工厂、比亚迪工厂等等专门造轿车)

关键实现 ①抽象出一个工厂类;②工厂类提供工厂方法;③具体的工厂(子产品工厂)实现工厂类

2.1 代码实现

首先抽象出一个工厂类

为啥叫抽象呢?是因为这个工厂不干具体的事,只定义了一个造车方法

// 抽象工厂--负责生产ICar
public abstract class CarFactory {  
    // 工厂方法
    public abstract ICar buildCar();  
}
复制代码

实现具体的工厂(别克工厂、凯迪拉克工厂)

public class BuickFactory extends CarFactory {  
    @Override  
    public ICar buildCar() {  
        return new BuickCar();  
    }  
}

public class CadillacFactory extends CarFactory {  
    @Override  
    public ICar buildCar() {  
        return new CadillacCar();  
    }  
}
复制代码

OK。分别造一辆别克、一辆凯迪拉克的轿车

public class FactoryMethodDemo {  
    public static void main(String[] args) { 
        // 别克轿车
        CarFactory buickFactory = new BuickFactory();  
        ICar buickCar = buickFactory.buildCar();  
        buickCar.start();  
        buickCar.run();  
  
        // 凯迪拉克轿车
        CarFactory cadillacFactory = new CadillacFactory();  
        ICar cadillacCar = cadillacFactory.buildCar();  
        cadillacCar.start();  
        cadillacCar.run();  
    }  
}
复制代码

2.2 工厂方法 vs 简单工厂

工厂方法模式中每一个子产品都对应一个工厂,解决了子产品过多时,简单工厂模式工厂类过于庞大的问题

符合开闭原则,增加车辆品牌只需增加具体类和对应的工厂类就OK(当然这也是它的缺点,系统类中的个数会成倍增加)

3 抽象工厂模式

像是专业工厂的做大版本,不满足于只生产轿车了,还要造SUV。改为多个工厂、每个工厂生产自己品牌的轿车、SUV(别克工厂、凯迪拉克工厂、比亚迪工厂等等,但不只造轿车了,还造SUV)

关键实现 ①抽象出一个工厂类;②工厂类提供工厂方法;③具体的工厂(子产品工厂)实现工厂类

3.1 产品等级 & 产品族

What?这关键实现不和工厂方法模式一毛一样吗?

确实

不过抽象工厂可以生产轿车和SUV,而工厂方法模式只能生产轿车,这就是它们的区别

用抽象工厂模式的概念来说,这里所谓的轿车和SUV叫产品族,而别克、凯迪拉克、比亚迪等叫产品等级

3.2 代码实现

新增一个SUV对象的ISuv接口(造出来的SUV能启动、能跑)

public interface ISuv {
    void start();
    void run();
}
复制代码

实现ISuv接口(别克SUV、凯迪拉克SUV)

public class BuickSuv implements ISuv {
    @Override
    public void start() {
        System.out.println("别克SUV启动");
    }
    @Override
    public void run() {
        System.out.println("别克SUV定速巡航");
    }
}

public class CadillacSuv implements ISuv {
    // 很简单,不写了 
}
复制代码

抽象出一个工厂类

但这个工厂类定义了两个造车方法(2个产品等级)

// 抽象工厂
public abstract class AbstractFactory {
    // 造轿车
    public abstract ICar buildCar();
    // 造SUV
    public abstract ISuv buildSuv();
}
复制代码

实现具体的工厂(别克工厂、凯迪拉克工厂)

public class BuickFactory extends AbstractFactory {
    @Override
    public ICar buildCar() {
        return new BuickCar();
    }
    @Override
    public ISuv buildSuv() {
        return new BuickSuv();
    }
}

public class CadillacFactory extends AbstractFactory {
    @Override
    public ICar buildCar() {
        return new CadillacCar();
    }
    @Override
    public ISuv buildSuv() {
        return new CadillacSuv();
    }
}
复制代码

OK。分别造一辆别克轿车、一辆凯迪拉克SUV

public class AbstractFactoryDemo {
    public static void main(String[] args) {
        AbstractFactory buickFactory = new BuickFactory();
        // 别克轿车
        ICar buickCar = buickFactory.buildCar();
        buickCar.start();
        buickCar.run();

        // 凯迪拉克SUV
        AbstractFactory cadillacFactory = new CadillacFactory();
        ISuv cadillacSuv = cadillacFactory.buildSuv();
        cadillacSuv.start();
        cadillacSuv.run();
    }
}
复制代码

3.3 优缺点

优点 包含工厂方法的优点,且通过实例工厂类对产品族进行约束

想象一下成套成套的换QQ皮肤,可以用A皮肤的工厂拿到A套装,用B皮肤的工厂拿到B套装,而不会出现拿乱套装的情况

缺点 拓展产品族困难(扩展产品等级倒是很容易,新增工厂就行)

拓展产品族要在AbstractFactory中增加抽象方法,导致所有实现了AbstractFactory的类都要修改,工作量太大

总结

简单工厂一个工厂类生产同一产品等级的对象(一个轿车工厂,能生产别克、凯迪拉克、比亚迪、特斯拉等),足够简单,但不符合开闭原则,子产品过多时工厂类会很庞大

工厂方法 简单工厂的专精版本,多个工厂类生产同一产品等级的对象(有多个工厂、每个工厂生产自己品牌的轿车),符合开闭原则,解决了简单工厂子产品过多时工厂类会很庞大的缺点,但系统类中的个数也会成倍增加

抽象工厂 专业工厂的做大版本,多个工厂类生产一个产品族的对象(每个工厂不满足于只生产轿车了还要造SUV),包含工厂方法的优点,且通过实例工厂类对产品族进行约束;拓展产品族困难,拓展产品等级简单

工厂方法加一个产品等级就变成了抽象工厂,抽象工厂只有一个产品等级时就变成了工厂方法,实际开发时不用纠结到底用哪个模式。此外,强大的 Spring 通过 Bean 注入和反射机制规避了简单工厂的缺点,基于 SpringBoot 开发时可用@Autowried + Map实现简单工厂哦

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PyTorch笔记

Tensor torch中的Tensor是一种数据结构,使用上与Python的list、numpy的array、ndarray等数据结构类似,可以当成一个多维数组来用。 数学上对张量有特定定义,但通常理解为多维数组即可。 生成Tensor:torch包中提供了直接生成Tens…

【微信小程序】初识微信小程序组件

作者简介:一名C站萌新,前来进行小程序的前进之路博主主页:大熊李子🐻 一、组件的创建与引用 1.1 创建组件 在项目的根目录中,鼠标右键,创建 components -> test 文件夹在新建的 components -> test…

十分钟验证一个轻量化车联网解决方案

智能网联汽车在车联网的应用上,通常是以智能传感器、物联网、GIS技术为基础,结合大数据、人工智能技术,通过OT(Operation tecnology)和IT(information tecnology)融合的方式,实现智能…

2.3 连续性随机变量

思维导图: 学习目标: 我会按照以下步骤学习连续型随机变量: 复习概率论的基础知识,包括概率、期望、方差等概念和公式,以及离散型随机变量的概率分布函数和概率质量函数的概念和性质。 学习连续型随机变量的概念和性…

学生信息管理系统(student information manage system, SIMS)

一、前言 本项目为学生信息管理系统,使用C语言编写。 ★★★项目详见本人gitee仓库,地址 https://gitee.com/omnipotent-brother/student-information-manage-system.git ★★★ 二、项目介绍 开发环境: 基于windows 11系统下的Visual Studio…

YC-A11(原创)基于springboot,vue网上商城

绪论 课题的开发背景 随着计算机和网络的快速发展,并且越来越普及,互联网日益成为人们收集信息常用渠道,电子商务开始流行,一种全新的理念不断形成并且快速发展,像国内电商巨头淘宝、京东、苏宁易购、唯品会等电商平台…

【JavaScript】2.JavaScript函数

JavaScript 函数 1. 函数的概念 函数&#xff1a;就是封装了一段可被重复调用执行的代码块 通过此代码块可以实现大量代码的重复使用 2. 函数的使用 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta na…

前馈PID控制(热交换器/反应釜温度控制)

如何利用PID进行温度控制请参看下面博客文章: 博途PID 1200/1500PLC PID_Compact比例作用权重b微分作用权重c解读(PI-D控制器 I-PD控制器)_RXXW_Dor的博客-CSDN博客很多人会问PLC自带的PID指令和我们自己设计的PID有什么区别,这个问题要看你和什么PID控制器作对比,PID负反…

NDK RTMP直播客户端二

在之前完成的实战项目【FFmpeg音视频播放器】属于拉流范畴&#xff0c;接下来将完成推流工作&#xff0c;通过RTMP实现推流&#xff0c;即直播客户端。简单的说&#xff0c;就是将手机采集的音频数据和视频数据&#xff0c;推到服务器端。 接下来的RTMP直播客户端系列&#xff…

Redis用于全局ID生成器、分布式锁的解决方案

全局ID生成器 每个店铺都可以发布优惠卷 当用户抢购时&#xff0c;就会生成订单并保存到tb_voucher_order这张表中&#xff0c;而订单表如果使用数据库自增id就存在一些问题&#xff1a; 1.id的规律性太明显 2.受单表数据量的限制 全局ID生成器&#xff0c;是一种在分布式系…

Atlassian后Server时代 | Server版vs.数据中心版,二者的区别在哪里?

2024年2月&#xff0c;也就是一年不到&#xff0c;Atlassian将终止对Server产品及插件的所有支持。 此公告发布后&#xff0c;许多用户需要了解怎样的前进方向才是最适合企业的。为此&#xff0c;Atlassian提供了本地部署的数据中心&#xff08;Data Center&#xff09;版以及云…

线段树笔记草稿

一个左节点u << 1和右节点u << 1 | 1 的证明 区间修改部分 1.批量等值修改 前提条件 是要区间修改&#xff0c;区间查询&#xff0c;且修改操作修改的值是相同的 情景 一般是要对一个数组执行k次操作&#xff0c;每次改变其中一个区间内所有元素的值&#x…

ChatGPT文本框再次升级,打造出新型操作系统

在ChatGPT到来之前&#xff0c;没有谁能够预见。但是&#xff0c;它最终还是来了&#xff0c;并引起了不小的轰动&#xff0c;甚至有可能颠覆整个行业。 从某种程度上说&#xff0c;ChatGPT可能是历史上增长最快的应用程序&#xff0c;仅在两个多月就拥有了1亿多活跃用户&…

Adaptive Weight Assignment Scheme For Multi-task Learning

Adaptive Weight Assignment Scheme For Multi-task Learning 题目Adaptive Weight Assignment Scheme For Multi-task Learning译题用于多任务学习的自适应权重分配方案时间2022年期刊/会议IAES International Journal of Artificial Intelligence (IJ-AI) 摘要&#xff1a;如…

【AutoGPT】你自己运行,我先睡了—— ChatGPT过时了吗?

系列文章目录 【AI绘画】Midjourney和Stable Diffusion教程_山楂山楂丸的博客-CSDN博客 目录 系列文章目录 前言 一、AutoGPT是什么&#xff1f; 二、AutoGPT带来的利弊 三、AutoGPT和ChatGPT区别 四、未来 总结 前言 ChatGPT是否过时&#xff1f;AutoGPT的兴起&#…

MappingGenerator PRO 2023.3 Visual Studio 2019-2022

您的私人编码助手 MappingGenerator 最初是作为 AutoMapper 的设计时替代品创建的。现在它正在演变为编码助手&#xff0c;您可以将最平凡的编码任务委派给它&#xff1a; 生成映射生成显式转换实施克隆生成投影表达式脚手架方法调用脚手架对象创建清理方法调用方便ILogger的使…

ChatGPT风口下的中外“狂飙”,一文看懂微软、谷歌、百度、腾讯、华为、字节跳动们在做什么?

毫无疑问&#xff0c;ChatGPT正成为搅动市场情绪的buzzword。 历史经历过无线电&#xff0c;半导体&#xff0c;计算机&#xff0c;移动通讯&#xff0c;互联网&#xff0c;移动互联网&#xff0c;社交媒体&#xff0c;云计算等多个时代&#xff0c;产业界也一直在寻找Next Bi…

Golang每日一练(leetDay0031)

目录 91. 解码方法 Decode Ways &#x1f31f;&#x1f31f; 92. 反转链表 II Reverse Linked List II &#x1f31f;&#x1f31f; 93. 复原 IP 地址 Restore IP Addresses &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练…

【JVM】JVM之执行引擎

文章目录一、前言二、名词解释机器码指令指令集汇编语言高级语言字节码虚拟机&物理机前端编译器&后端编译器三、JVM之执行引擎执行引擎是如何工作的&#xff1f;解释器即时编译器&#xff08;JIT&#xff09;分层编译策略虚拟机执行模式热点代码&探测方式1&#xf…

如何在 Linux 中使用 Chage 命令,修改Linux系统用户密码更改策略

Chage是一个用于修改Linux系统用户密码更改策略的命令行工具。在本文中&#xff0c;我们将介绍如何在Linux系统中使用Chage命令。 检查用户密码过期信息 使用Chage命令可以检查用户密码更改策略和过期信息。要检查特定用户的密码过期信息&#xff0c;可以使用以下命令&#x…