【设计模式】2.工厂模式

news2025/7/29 6:42:40

文章目录

  • 1. 工厂模式概述
  • 2. 简单工厂模式
  • 3. 工厂方法模式
  • 4. 抽象工厂模式

1. 工厂模式概述

工厂模式属于创建型模式的一种。

在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则

工厂模式将目的将创建对象的具体过程屏蔽隔离起来,从而达到更高的灵活性,使得如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦

开闭原则:

开闭原则要求对 扩展开放(对提供方),对修改关闭(对使用方)

工厂模式分为以下三种:

  • 简单工厂模式(不属于GOF的23种经典设计模式)
  • 工厂方法模式
  • 抽象工厂模式

2. 简单工厂模式

简单工厂不是一种设计模式,反而比较像是一种编程习惯

简单工厂模式的核心是定义一个创建对象的接口将对象的创建和本身的业务逻辑分离,降低系统的耦合度,使得两个修改起来相对容易些,当以后实现改变时,只需要修改工厂类即可。

简单工厂包含如下角色:

  • 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品 :实现或者继承抽象产品的子类
  • 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。

实现简单工厂模式的基本思路是什么?

简单工厂的实现思路是,定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口。简单工厂适用于需要创建的对象较少或客户端不关心对象的创建过程的情况

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VKO6QEBf-1668690825240)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/9944/%E7%AE%80%E5%8D%95%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F.png)]

工厂类代码如下:

public class SimpleCoffeeFactory {

    public Coffee createCoffee(String type) {
        Coffee coffee = null;
        if("americano".equals(type)) {
            coffee = new AmericanoCoffee();
        } else if("latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        return coffee;
    }
}

咖啡店类

public class CoffeeStore {

    public Coffee orderCoffee(String type) {

        SimpleCoffeeFactory factory = new SimpleCoffeeFactory();
        //调用生产咖啡的方法
        Coffee coffee = factory.createCoffee(type);

        //加配料
        coffee.addMilk();
        coffee.addsugar();

        return coffee;
    }
}

测试类

public class Client {
    public static void main(String[] args) {
        //创建咖啡店类对象
        CoffeeStore store = new CoffeeStore();
        Coffee coffee = store.orderCoffee("latte");

        System.out.println(coffee.getName());
    }
}

工厂(factory)处理创建对象的细节,一旦有了SimpleCoffeeFactory,CoffeeStore类中的orderCoffee()就变成此对象的客户,后期如果需要Coffee对象直接从工厂中获取即可。这样也就解除了和Coffee实现类的耦合,同时又产生了新的耦合,CoffeeStore对象和SimpleCoffeeFactory工厂对象的耦合,工厂对象和商品对象的耦合。

后期如果再加新品种的咖啡,我们势必要需求修改SimpleCoffeeFactory的createCoffee方法的代码,违反了开闭原则。工厂类的客户端可能有很多,比如创建美团外卖等,这样只需要修改工厂类的代码,省去其他的修改操作。

简单工厂模式有什么优点?

简单工厂模式封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。

简单工厂模式有什么缺点?

增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。

简单工厂模式还可以怎么实现?

简单工厂模式还可以使用静态工厂的方式实现,也就是将创建对象功能定义成静态的。

public class SimpleCoffeeFactory {

    public static Coffee createCoffee(String type) {
        Coffee coffee = null;
        if("americano".equals(type)) {
            coffee = new AmericanoCoffee();
        } else if("latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        return coffe;
    }
}

3. 工厂方法模式

工厂方法模式将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B4Jo4q8C-1668690825241)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/9944/%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95%E6%A8%A1%E5%BC%8F.png)]

工厂方法模式的主要角色:

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
  • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

具体实现:

抽象工厂

public interface CoffeeFactory {

    Coffee createCoffee();
}

具体工厂

public class LatteCoffeeFactory implements CoffeeFactory {

    public Coffee createCoffee() {
        return new LatteCoffee();
    }
}

public class AmericanCoffeeFactory implements CoffeeFactory {

    public Coffee createCoffee() {
        return new AmericanCoffee();
    }
}

咖啡店类

public class CoffeeStore {

    private CoffeeFactory factory;

    public CoffeeStore(CoffeeFactory factory) {
        this.factory = factory;
    }

    public Coffee orderCoffee(String type) {
        Coffee coffee = factory.createCoffee();
        coffee.addMilk();
        coffee.addsugar();
        return coffee;
    }
}

测试类

public class Client {
    public static void main(String[] args) {
        //创建咖啡店对象
        CoffeeStore store = new CoffeeStore();
        //创建对象
        //CoffeeFactory factory = new AmericanCoffeeFactory();
        CoffeeFactory factory = new LatteCoffeeFactory();
        store.setFactory(factory);

        //点咖啡
        Coffee coffee = store.orderCoffee();

        System.out.println(coffee.getName());
    }
}

由上面的代码可见,当我们需要添加产品的时候也需要添加相应的工厂类,但是却不用修改工厂类的代码,这样就解决了简单工厂模式的缺点。

工厂方法模式是简单工厂模式的进一步抽象。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。

工厂方法模式有什么优点?

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

工厂方法模式有什么缺点?

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

4. 抽象工厂模式

在工厂方法模式中,我们使用一个工厂创建一个产品,一个具体工厂对应一个具体产品,但有时候我们需要一个工厂能够提供多个产品对象,而不是单一的对象,这个时候我们就需要使用抽象工厂模式。

image-20200401214509176

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

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

抽象工厂模式的主要角色如下:

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C8tYIWEU-1668690825242)(https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/9944/%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F.png)]

抽象工厂

public interface DessertFactory {

    Coffee createCoffee();

    Dessert createDessert();
}

具体工厂

//美式甜点工厂
public class AmericanDessertFactory implements DessertFactory {

    public Coffee createCoffee() {
        return new AmericanCoffee();
    }

    public Dessert createDessert() {
        return new MatchaMousse();
    }
}
//意大利风味甜点工厂
public class ItalyDessertFactory implements DessertFactory {

    public Coffee createCoffee() {
        return new LatteCoffee();
    }

    public Dessert createDessert() {
        return new Tiramisu();
    }
}

测试类

public class Client {
    public static void main(String[] args) {
        //创建的是意大利风味甜品工厂对象
        //ItalyDessertFactory factory = new ItalyDessertFactory();
        AmericanDessertFactory factory = new AmericanDessertFactory();
        //获取拿铁咖啡和提拉米苏甜品
        Coffee coffee = factory.createCoffee();
        Dessert dessert = factory.createDessert();

        System.out.println(coffee.getName());
        dessert.show();
    }
}

抽象工厂模式有什么优点?

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

抽象工厂模式有什么缺点?

当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

抽象工厂模式的应用场景有哪些?

  • 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。

  • 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。

  • 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

如:输入法换皮肤,一整套一起换。生成不同操作系统的程序。

抽象工厂模式与工厂方法模式的区别?

  1. 工厂方法只有一个抽象产品类和一个抽象工厂类,但可以派生出多个具体产品类和具体工厂类,每个具体工厂类只能创建一个具体产品类的实例。

  2. 抽象工厂模式拥有多个抽象产品类(产品族)和一个抽象工厂类,每个抽象产品类可以派生出多个具体产品类;抽象工厂类也可以派生出多个具体工厂类,同时每个具体工厂类可以创建多个具体产品类的实例

请你比较以下简单工厂模式、工厂方法模式和抽象工厂模式的异同?

  • 简单工厂模式其实并不算是一种设计模式,更多的时候是一种编程习惯。简单工厂的实现思路是,定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口。
  • 工厂方法模式是简单工厂的仅一步深化, 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。工厂方法的实现思路是,定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。
  • 抽象工厂模式是工厂方法的仅一步深化,在这个模式中的工厂类不单单可以创建一个对象,而是可以创建一组对象。这是和工厂方法最大的不同点。抽象工厂的实现思路是,提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

参考:

  • Java设计模式之创建型:工厂模式详解(简单工厂+工厂方法+抽象工厂)_张维鹏的博客-CSDN博客
  • 【面试最常见的设计模式之工厂模式】_硕风和炜的博客-CSDN博客_工厂模式 面试
  • 黑马程序员Java设计模式详解, 23种Java设计模式(图解+框架源码分析+实战)

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

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

相关文章

图神经网络学习笔记

1 图神经网络应用 芯片设计、场景分析问题推理、推荐系统、欺诈检测风控相关、道路交通动态流量预测、自动驾驶、无人机等、化学医疗等场景 2 图神经网络基本组成 点(vertex)、边(edge)、全局图(global),图神经网络(GNN,Graph Neural Netw…

Java 集合知识点总结

Java 集合知识点总结总览Collection 接口ListArrayList源码&扩容机制SetQueueMap接口HashMapHashMap源码&底层数据结构HashMap 的遍历LinkedHashMapTreeMapHashtableConcurrentHashMap 源码&底层数据结构本文是个人阅读学习JavaGuide的集合知识的总结笔记。总览 C…

【计算机毕业设计】个人交友网站源码

一、系统截图(需要演示视频可以私聊) 摘 要 本论文主要论述了如何使用JAVA语言开发一个个人交友网站,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中&#xff0…

【最强最全车牌识别算法】支持13种中文车牌识别的云端API部署(可直接获取源码使用)

项目简介 在城市交通管理、视频监控、车辆识别和停车场管理中车辆检测与车牌识别是一项富有挑战而重要的任务。利用深度学习识别不同条件下的车辆及其车牌信息。更具体地说,实时目标检测网络(Yolov5)用于从车辆图像中提取特征并且通过训练对…

[附源码]java毕业设计面试刷题系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

基于分组码的消息验证码的程序实现

目 录 摘 要 I 1 绪论 1 1.1 课题研究背景和意义 1 1.2 课题研究现状 1 2 CBC MAC的特征和基本工作原理 2 2.1 CBC MAC的特征和码集选择的原则 2 2.2 CBC MAC生成原理 2 2.3 CBC MAC模块结构图 3 3 FPGA和VHDL语言 4 3.1 概述 4 3.2 VHDL语言特点 5 3.2.1 常用硬件描述语言简介…

GUI编程--PyQt5--QAbstractButton

文章目录绘制事件设置文本设置快捷键设置自动重复按钮状态排他性按钮的点击按钮点击有效区域按钮的信号QAbstractButton是一个抽象类,无法直接使用。绘制事件 from PyQt5.QtWidgets import QAbstractButton from PyQt5.QtGui import QPainter, QPen, QColor # 定义…

loki单机对接minio

安装minio 请参考minio官方文档部署 创建Buckets 配置Policy策略 创建一个loki的policy,授权内容如下 (权限配置请参考aws的s3权限配置) { "Version": "2012-10-17", "Statement": [ { …

部署安装yapi

配置环境 部署安装yapi 前提是配置环境,需要 nodejs(7.6)mongodb(2.6) 这里我使用docker 安装上面的nodejs 或 mongodb docker 安装 mongodb 教程: 使用docker 安装MongoDB数据库_小周sir的码农的博客-CSDN博客Doc…

删除pip下载的所有第三方库,最快的方法,没有之一

1、问题描述 初学Python的朋友,经常会使用pip下载各种各样的第三方库,例如自动化办公的专用库:python-office。 下载了很多库会占用电脑空间,而且互相之间有很多依赖关系,也不知道怎么样才能卸载干净。 虽然卸载的方法…

一起学习集合框架之 TreeSet

什么是 TreeSet TreeSet 是一个具有唯一元素的二叉树的集合,又被翻译为 树集。Java 中的 TreeSet 类是 Java 集合框架的一部分,从 Java 6 开始,它实现了 NavigableSet 接口(这个接口增加了几个查找元素以及反向遍历的便利方法&am…

【快速上手系列】使用MD5加密对密码进行加密

【快速上手系列】使用MD5加密对密码进行加密 介绍 MD5加密 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)应用程序的密码通常不会明文保存,会使用各种各样的加密算法对密码进行加密MD5算法相对来说较为安全。初始的MD5算法是…

开发微信小程序的流程_微信小程序开发的作用

小程序的快速发展和围绕其诞生的产业链逐步完善,更多的平台和流量开始参与到小程序的开发领域,推出属于平台的小程序接口。相较于传统的线下广告宣传模式,小程序的传播和推广拥有互联网便捷高效的属性。用户扫描二维码就能关注公众号&#xf…

【安全测试学习】自动化注入攻击之 FuzzDB和Burp 组合拳

一、FuzzDB 开源的应用程序模糊测试数据库,包含了各种攻击 payload 的测试用例集合。 主要功能: OS 命令注入 目录遍历 文件上传绕过 身份验证绕过 XSS SQL 注入 HTTP 头注入 CRLF 注入 NoSQL 注入等 还包含了一些用不同语言写成的 webshell 与常用的账…

什么是 MQ

MQ的概念 MQ (Message Queue)消息队列,是在消息传输过程中存储消息的容器。多用于分布式系统之间的通信。 队列是基础数据结构中 “先进先出” 的一种数据结构。 消息对列,指把要传输的数据消息放在队列中,用队列机制…

spring之基于p命名c命名空间的注入

文章目录前言一、p命名空间1.1、编写一个普通的Java类1.2、spring配置文件1.3、测试1.4、运行结果二、c命名空间2.1、编写一个普通的Java类2.2、spring配置文件2.3、测试2.4、运行结果总结前言 P命名空间注入: 目的:简化set方法注入 使用p命名空间注入的…

C++ 哈希表的总结与例题

文章目录CSTL哈希表设计哈希集合设计哈希映射哈希集合例题一:只出现一次的数字例题二:快乐数哈希映射例题一:两数之和例题二:两个列表的最小索引总和例题三:字符串中的第一个唯一字符设置键例题一:字母异位…

安全进阶:虚拟防火墙基础实验

实验拓扑 网络拓扑及IP编址如上图所示; 实验需求 PC2与Server2属于一个敏感的业务,这个业务的流量要求与防火墙上的其他流量完全隔离,使用虚拟防火墙技术实现这个需求; PC2要求能够访问Server2;PC2属于Trust域&#…

Exception in thread “main“ java.lang.UnsupportedOperationException解决办法

1.首先报错UnsupportedOperationException 是因为我们用的是 List<Integer> list1 Arrays.asList(2, 3, 5);这个方式获取的集合,该集合底层没有重写一些方法,所以报错 解决方案 定义新集合接收上一步的数据,然后用新集合来操作就行 package day01;import java.util.A…

元数据管理-解决方案调研二:元数据管理解决方案——Saas/内部解决方案(1)

Saas/内部解决方案 2.1、Data Galaxy 地址&#xff1a;The 360 Data Catalog for datagovernance - DataGalaxy 特点&#xff1a;实现数据治理最佳方式 1、理解业务数据并可以共享通用定义&#xff1b;即由团队成员共同维护定义业务术语词汇的知识库 2、统一企业数据字典&…