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

news2024/11/15 15:29:24

前言

工厂模式(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实现简单工厂哦

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

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

相关文章

RecvByteBufAllocator内存分配计算

虽然了解了整个内存池管理的细节,包括它的内存分配的具体逻辑,但是每次从NioSocketChannel中读取数据时,应该分配多少内存去读呢? 例如,客户端发送的数据为1KB , 应该分配多少内存去读呢? 例如:…

梳理ERP与CRM、MRP、PLM、APS、MES、WMS、SRM的关系

数字化转型中少不了ERP系统的存在,CRM、MRP、PLM、APS、MES、WMS、SRM这些系统都需要一起上吗? 如下图所示,是某企业IT系统集成架构流图。 先了解一下ERP是做什么的,ERP就是企业资源管理系统,从企业的价值链分析&…

在CSDN创作了6个月,我收获了什么?文末送书~

作者主页:阿玥的小东东主页! 正在学习:python和C/C 期待大家的关注哦 目录 一次很好的机会,让我开始了CSDN之旅 首先来看看我的几位领路人 创作动力 1W粉丝 在CSDN我收获了什么? 很高的展现量 认证创作者身份 社…

构建自动过程:FinalBuilder 8.0 Crack

使用 FinalBuilder 自动化您的构建过程很简单。使用 FinalBuilder,您无需编辑 xml 或编写脚本。可视化定义和调试您的构建脚本,然后使用 Windows 调度程序安排它们,或将它们与 Continua CI、Jenkins 或任何其他 CI 服务器集成。 成千上万的软…

手把手调参 YOLOv8 模型之 训练|验证|推理配置-详解

YOLO系列模型在目标检测领域有着十分重要的地位,随着版本不停的迭代,模型的性能在不断地提升,源码提供的功能也越来越多,那么如何使用源码就显得十分的重要,接下来通过文章带大家手把手去了解Yolov8(最新版…

Android开发—Jetpack四件套

2017年,Google发布了Android Architecture Components,包括Room、LiveData、ViewModel和Paging等组件,旨在帮助开发者更轻松地实现MVVM架构。 2018年,Google在I/O大会上推出的一套Android开发组件库,旨在帮助开发者更…

Python 小型项目大全 56~60

五十六、质数 原文:http://inventwithpython.com/bigbookpython/project56.html 质数是只能被 1 和它自己整除的数。质数有各种各样的实际应用,但是没有算法可以预测它们;我们必须一次计算一个。然而,我们知道有无限多的质数有待发…

技术招聘漫谈 | Java工程师招聘难?你可能需要这份独家指南

两周前,我们发布了一篇关于怎样招聘前端工程师的文章(点击此处顾)。在文章中,我们分析了前端岗位有哪些必不可少的考察要点,以及如何在面试中考核对方是否能写出高质量的代码,这篇文章得到了大量技术面试官…

高完整性系统工程(四): An Overview of Alloy

目录 1. 概述 2. 指定软件设计 3. 验证设计规范 4. 验证预期属性 1. 概述 在第一章中,我们将解释如何使用 Alloy 来探索一个非常简单的软件组件的设计,即大多数操作系统中存在的众所周知的垃圾箱 或回收站。目的是对如何使用 Alloy 指定和分析软件设…

MyBatis注解开发---实现自定义映射关系和关联查询

目录 一、使用注解实现自定义映射关系 1. 编写注解方法 2. 编写测试方法 3. 查看运行结果 二、使用注解实现一对一关联查询 1. 编写注解方法 2. 编写测试方法 3. 查看运行结果 三、使用注解实现一对多关联查询 1. 编写注解方法 2. 编写测试方法 3. 查看运行结果 四…

List接口中的ArrayList与LinkedList

ArrayList ArrayList的继承实现关系图 ArrayList 底层就是⼀个 Object[] 数组,当实例化ArrayList时没有指定数组容量大小,、第⼀次添加元素(调⽤ add() ⽅法)时会初始化为⼀个⻓度为 10 的数组(即默认初始化容量为 1…

[Netty源码] ByteBufAllocator内存管理器相关问题 (十一)

文章目录1.ByteBufAllocator 内存管理器2.UnpooledByteBufAllocator2.1 heap内存的分配2.2 direct内存的分配3.PooledByteBufAllocator3.1 heap内存和direct内存的分配3.2 directArena分配direct内存的流程3.3 内存规格的介绍4.缓存的相关问题4.1 缓存的数据结果4.2 命中缓存的…

一维差分思想【算法推导、深刻思考】

797. 差分 - AcWing题库 差分本质上就是前缀和的逆运算 算法推导 其实在最开始自己去完成这个题目的时候,感觉好像是可以往前缀和方向靠的,但是一下子没有想到实现方法就无疾而终了。所以最后选择的算法就只是单纯的暴力(虽然知道过不了&…

【操作系统复习】第5章 存储器管理

存储器的层次结构 存储层次 ➢ CPU寄存器 ➢ 主存:高速缓存、主存储器、磁盘缓存 ➢ 辅存:固定磁盘、可移动介质 层次越高,访问速度越快,价格也越高,存储容量也最小 寄存器和主存掉电后存储的信息不再存在&a…

2024软件工程考研之《软件工程导论》专业课复习

一、考察《软件工程导论》的学校 截止目前,考察《软件工程导论》的学校主要有: 大连理工大学887 北京航天航空大学991 北京交通大学901 河海大学846 海南大学835 新疆大学841 成都信息工程大学809 长安大学846 天津工业大学840 华东交通大学837 大连交通…

采购招投标系统-高效管控招采流程-降低采购成本

项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及…

软考证书找工作有用吗?软考找工作用处大吗

软考证书是衡量IT技术人才能力的一种重要评价标准。 一、软考高级证书对找工作的帮助 1. 竞争力增强 软考高级证书具有一定难度和较高的专业技能要求,拥有该证书的人的技术水平和专业能力会得到认可和尊重,从而增强求职者的竞争力。 2. 拓宽职业发展…

防火墙NAT实验,双机热备实验

目录 NAT防火墙基础实验 源地址转换 服务器映射 域内双向NAT 域间双向NAT 双机热备基础实验 主备备份 负载分担 NAT防火墙基础实验 实验拓扑: 1.进入防火墙图形化页面进行配置 接口列表的配置 源地址转换 企业内部网络访问外部网络,进行源地…

如何用nodejs构造一个网站爬虫

爬虫是个什么东西 英文spider,网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些…

干货分享 | 采购没“云”和有云的区别有哪些?

多年前,提起“云”这个词,很多人还是“不知所云”。 但如今,大众对“云”的了解和认可程度也越来越高,尽情享受着“云”带来的便利。 通过“云”,可以随时随地畅听海量音乐、进行网购、访问云盘的照片和视频、在云端创…