03-JAVA设计模式-工厂模式详解

工厂模式

工厂设计模式是一种创建型设计模式,它提供了一种封装对象创建过程的机制,将对象的创建与使用分离。
这种设计模式允许我们在不修改客户端代码的情况下引入新的对象类型。
在Java中,工厂设计模式主要有三种形式:简单工厂模式、工厂方法模式和抽象工厂模式。

简单工厂模式

用来生成同一等级结构中的任意产品。

注:对增加新的产品需要修改已有的代码,这违背了面向对象设计原则中的开闭原则(对扩展开放,对修改关闭)

UML

在这里插入图片描述

实现代码

Animal.java

// 定义一个动物的接口
public interface Animal {

    // 接口中定义一个抽象的方法:叫声
    void makeSound();
}

Cat.java

// 定义一个实现类实现Animal接口
public class Cat implements Animal{
    // 猫属于动物:实现发出叫声的接口
    @Override
    public void makeSound() {
        System.out.println("喵喵喵");
    }
}

Dog.java

// 定义一个实现类实现Animal接口
public class Dog implements Animal{
    // 狗属于动物:实现发出叫声的接口
    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }
}

SimpleAnimalFactory.java

// 定义一个简单工厂类用于创建动物
public class SimpleAnimalFactory {
    // 定义一个创建动物的方法用于生产不同的动物的静态方法
    public static Animal createAnimal(String type) {
        if ("Cat".equalsIgnoreCase(type)) {
            return new Cat();
        }
        else if ("Dog".equalsIgnoreCase(type)) {
            return new Dog();
        }
        else  {
           return null;
        }
    }
}

TestClient.java

public class TestClient {
    public static void main(String[] args) {
        // 根据简单工厂创建不同的动物,执行动作
        // 生产一个Cat
        Animal cat = SimpleAnimalFactory.createAnimal("cat");
        cat.makeSound();
        // 生产一个Dog
        Animal dog = SimpleAnimalFactory.createAnimal("Dog");
        dog.makeSound();
    }
}

执行结果:

在这里插入图片描述

结论:

简单工厂好处在于,对于客户端调用时,我们不需要关心具体实现,只需要调用工厂方法,传入参数获取我们需要返回的结果即可。

但是对于同一个产品(动物),如果我们进行新增(猪),则必须要修改Factory中createAnimal(String type)方法。因此违背了开闭原则

工厂方法模式

用来生产同一等级结构中的固定产品。

支持增加任意产品,满足开闭原则,但设计相对于简单工厂复杂一些

UML

在这里插入图片描述

实现代码

Product.java

// 定义一个产品接口
public interface Product {
    //定义一个抽象的使用的方法
    void use();
}

ProductA.java

// ProductA实现Product接口
public class ProductA implements Product{
    @Override
    public void use() {
        System.out.println("ProductA 使用了");
    }
}

ProductB.java

// ProductB实现Product接口
public class ProductB implements Product{
    @Override
    public void use() {
        System.out.println("ProductB 使用了");
    }
}

ProductFactory.java

// 定义一个ProductFactory工厂接口
public interface ProductFactory {
    // 接口中定义一个创建Product的方法
    Product createProduct();
}

ProductAFactory.java

// 创建一个ProductA的工厂,实现ProductFactory接口,用于生产ProductA
public class ProductAFactory implements ProductFactory{
    @Override
    public Product createProduct() {
        return new ProductA();
    }
}

ProductBFactory.java

// 创建一个ProductB的工厂,实现ProductFactory接口,用于生产ProductB
public class ProductBFactory implements ProductFactory{
    @Override
    public Product createProduct() {
        return new ProductB();
    }
}

TestClient.java

public class TestClient {
    public static void main(String[] args) {
        // 创建ProductA
        Product product1 = new ProductAFactory().createProduct();
        product1.use();
        // 创建ProductB
        Product product2 = new ProductBFactory().createProduct();
        product2.use();
    }
}

执行结果:

在这里插入图片描述

从工厂方式模式,我们可以看出,我们可以任意增加同一产品,而不会影响到原来已有产品
(创建一个产品C继承Product接口,创建一个产品C的Factory类生产C,使用是通过相应Factory调用生产C即可)。
如果产品中新增一个方法,则所有实现了Product接口的方法都必须修改相应方法。

抽象工厂模式

用来生产不同产品族的全部产品。

对增加新的产品无能为力,支持增加产品族

UML

在这里插入图片描述

实现代码

Engine.java

// 定义发动机接口
public interface Engine {
    // 定义发动机 发动方法
    void run();
    // 定义发动机 停止方法
    void stop();
}

HighEndEngine.java

// 创建一个高端发动机实现发动机
public class HighEndEngine implements Engine{
    @Override
    public void run() {
        System.out.println("高端发动机-跑的快");
    }
    @Override
    public void stop() {
        System.out.println("高端发动机-刹车性能强");
    }
}

LowEndEngine.java

// 创建一个低端发动机实现发动机
public class LowEndEngine implements Engine{
    @Override
    public void run() {
        System.out.println("低端发动机-跑的慢");
    }
    @Override
    public void stop() {
        System.out.println("低端发动机-刹车性能弱");
    }
}

CarBody.java

// 定义一个车身接口
public interface CarBody {
    // 定义一个乘坐的方法
    void ride();
}

HighEndCarBody.java

// 创建一个高端车身实现车身
public class HighEndCarBody implements CarBody{
    @Override
    public void ride() {
        System.out.println("高端车身-奢华-安全");
    }
}

LowEndCarBody.java

// 创建一个低端车身实现车身
public class LowEndCarBody implements CarBody{
    @Override
    public void ride() {
        System.out.println("低端车身-朴素-看起来安全");
    }
}

Tyre.java

// 定义一个轮胎接口
public interface Tyre {
    // 定义轮胎转动的方法
    void run();
}

HighEndTyre.java

// 创建一个高端轮胎实现轮胎
public class HighEndTyre implements Tyre{
    @Override
    public void run() {
        System.out.println("高端轮胎-太空材料-安全-耐磨");
    }
}

LowEndTyre.java

// 创建一个低端轮胎实现轮胎
public class LowEndTyre implements Tyre{
    @Override
    public void run() {
        System.out.println("低端轮胎-普通材料-易磨损");
    }
}

CarFactory.java

// 定义Car的接口
public interface CarFactory {
    // 创建发动机
    Engine engine();
    // 创建车身
    CarBody carBody();
    // 创建轮胎
    Tyre tyre();
}

HighEndCarBody.java

// 高端汽车工厂实现汽车工厂
public class HighEndCarFactory implements CarFactory{
    @Override
    public Engine engine() {
        return new HighEndEngine();
    }
    @Override
    public CarBody carBody() {
        return new HighEndCarBody();
    }
    @Override
    public Tyre tyre() {
        return new HighEndTyre();
    }
}

LowEndCarFactory.java

// 低端汽车工厂实现汽车工厂
public class LowEndCarFactory implements CarFactory{
    @Override
    public Engine engine() {
        return new LowEndEngine();
    }
    @Override
    public CarBody carBody() {
        return new LowEndCarBody();
    }
    @Override
    public Tyre tyre() {
        return new LowEndTyre();
    }
}

TestClient.java

public class TestClient {
    public static void main(String[] args) {
        // 使用高端汽车工厂类 创建高端汽车
        HighEndCarFactory highEndCar = new HighEndCarFactory();
        highEndCar.engine().stop();
        highEndCar.carBody().ride();
        highEndCar.tyre().run();

        System.out.println("==========================");

        // 使用低端汽车工厂类 创建低端汽车
        LowEndCarFactory lowEndCar = new LowEndCarFactory();
        lowEndCar.engine().stop();
        lowEndCar.carBody().ride();
        lowEndCar.tyre().run();
    }
}

执行结果:

在这里插入图片描述

抽象工厂,不可以增加产品(比如:CarFactory一旦定下了,如果我们要新增新的部件则所有实现CarFactory的类都需实现该方法)。
但是抽象工厂,可以根据已有的接口,创建更多的产品族(比如:定义一个中端汽车工厂,调用高端发动机,低端轮胎,低端车身,等任意组合成新的Factory)

对比及应用场景

简单工厂模式

  • 优点:
    • 实现了对象的创建和使用的责任分割,客户端只需要传入正确的参数,就可以获取需要的对象,无需知道创建细节。
    • 工厂类中有必要的判断逻辑,可以决定根据当前的参数创建对应的产品实例,客户端可以免除直接创建产品对象的责任。
  • 缺点:
    • 工厂类职责过重,如果产品种类增加,工厂类的代码会变得庞大且复杂,不利于维护。
    • 简单工厂模式违背了开放封闭原则,因为每次增加新产品时,都需要修改工厂类的代码。
  • 适用场景:
    • 创建对象较少,且对象的创建逻辑不复杂时。
    • 客户端不关心对象的创建过程,只关心使用对象时。

工厂方法模式

  • 优点:
    • 将对象的创建推迟到子类中进行,使得类的实例化更加灵活和可扩展。
    • 降低了客户端与具体产品类之间的耦合度,客户端只需要知道对应的工厂,无需知道具体的产品类。
  • 缺点:
    • 增加了系统的抽象性和理解难度,需要引入额外的工厂接口和工厂类。
    • 如果产品类较少,使用工厂方法模式可能会增加不必要的复杂性。
  • 适用场景:
    • 需要创建大量相似对象时,可以使用工厂方法模式来简化对象的创建过程。
    • 当一个类需要由其子类来指定创建哪个对象时,可以使用工厂方法模式。
    • 但实际开发中,简单工厂比工厂方法使用的更多

抽象工厂模式

  • 优点:
    • 提供了创建一系列相关或相互依赖对象的接口,无需指定它们具体的类。
    • 增加了系统的灵活性和可扩展性,可以通过更换不同的工厂来实现不同的产品族。
  • 缺点:
    • 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难。
    • 如果产品族中的产品较少,使用抽象工厂模式可能会导致代码冗余和复杂性增加。
  • 适用场景:
    • 当需要创建一组相互关联或相互依赖的对象时,可以使用抽象工厂模式。
    • 当一个系统需要独立地变化其创建的对象时,抽象工厂模式是一个很好的选择。

gitee源码

git clone https://gitee.com/dchh/JavaStudyWorkSpaces.git

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

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

相关文章

每日OJ题_优先级队列_堆③_力扣692. 前K个高频单词

目录 力扣692. 前K个高频单词 解析代码 力扣692. 前K个高频单词 692. 前K个高频单词 难度 中等 给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率&#xff0c…

潜水后可以戴耳机吗?精选四款防水游泳耳机,不惧水压挑战

随着生活水平的提高,人们越来越注重健康与休闲娱乐。潜水作为一项集运动、探险和乐趣于一身的活动,近年来受到了越来越多的关注。然而,在享受潜水带来的乐趣的同时,我们也希望能够在水下保持与外界的联系,例如欣赏音乐…

经济学 赋税

赋税: 1.为政府服务提供金钱来源 2. 用于保护环境 3.帮助国家使用财政和货币政策,推动经济增长 4.再分配社会财富的一种方式,平衡富人和穷人的贫富差距 5.帮助我们支付市场自身可能无法实现的服务,比如公共安全,国…

【MySQL】解决修改密码时报错:--skip-grant-tables option

首先我们先了解到为何会出现如上报错: 是因为我们在第一次配置MySQL中的my.cnf时,我们添加了–skip–grant-tables 选项 跳过验证身份的选项 所以,我们第一次登录成功后想要修改密码会出现如下报错: [hxiZ0jl69kyvg0h181cozuf5Z…

如何高效学习Python编程语言

理解Python的应用场景 不同的编程语言有不同的发展历史和应用场景,了解Python主要应用在哪些领域对于学习它会有很大帮助。Python最初是一种通用脚本语言,主要用于系统级任务自动化。随着时间的推移,它逐步成为数据处理、科学计算、Web开发、自动化运维等众多领域的主要编程语…

Vue - 3( 15000 字 Vue 入门级教程)

一:初识 Vue 1.1 收集表单数据 收集表单数据在Vue.js中是一个常见且重要的任务,它使得前端交互变得更加灵活和直观。 Vue中,我们通常使用v-model指令来实现表单元素与数据之间的双向绑定,从而实现数据的收集和更新。下面总结了…

深入浅出 -- 系统架构之负载均衡Nginx反向代理

一、Nginx反向代理-负载均衡 首先通过SpringBootFreemarker快速搭建一个WEB项目:springboot-web-nginx,然后在该项目中,创建一个IndexNginxController.java文件,逻辑如下: Controller public class IndexNginxControl…

卷积神经网络实战

构建卷积神经网络 卷积网络中的输入和层与传统神经网络有些区别,需重新设计,训练模块基本一致 1.首先读取数据 - 分别构建训练集和测试集(验证集) - DataLoader来迭代取数据 # 定义超参数 input_size 28 #图像的总尺寸28*28…

优雅强大的前端管理模板——Soybean Admin

公众号:【可乐前端】,每天3分钟学习一个优秀的开源项目,分享web面试与实战知识,也有全栈交流学习摸鱼群,期待您的关注! 每天3分钟开源 hi,这里是每天3分钟开源,很高兴又跟大家见面了&#xff0…

python 03序列(列表和元组)

列表 1.创建 x[1,2,3,4,5,6,7,8,9,10] print(x) 或者是 y[a,b,c,d,e,f,g,h] print(y) 2.访问 (1)取出一个元素 x[0] #取出第0号,即List里第一个元素 (2)取出多个连续元素 通过两个索引值实现,第一…

专题【双指针】【学习题】刷题日记

题目列表 11. 盛最多水的容器 42. 接雨水 15. 三数之和 16. 最接近的三数之和 18. 四数之和 26. 删除有序数组中的重复项 27. 移除元素 75. 颜色分类 167. 两数之和 II - 输入有序数组 2024.04.06 11. 盛最多水的容器 题目 给定一个长度为 n 的整数数组 height 。有 n 条垂…

MATLAB - mpcobj = mpc(model,ts,P,M,W,MV,OV,DV) 函数

系列文章目录 前言 模型预测控制器使用线性工厂、干扰和噪声模型来估计控制器状态并预测未来的工厂输出。控制器利用预测的设备输出,解决二次规划优化问题,以确定控制动作。 有关模型预测控制器结构的更多信息,请参阅 MPC 预测模型。 一、语法…

SpringMVC--概述 / 入门

目录 1. SpringMVC简介 2. 配置&入门 2.1. 开发环境 2.2. 创建maven工程 2.3. 手动创建 web.xml 2.4. 配置web.xml 2.4.1. 默认配置方式 2.4.2. 扩展配置方式 2.5. 创建请求控制器 2.6. 创建springMVC的配置文件 2.7. 测试 HelloWorld 2.7.1. 实现对首页的访问…

OJ在线比赛系统(人员管理、赛题发布、在线提交、题目审核、成绩录入)

系统功能设计 技术栈:springboot,jdk8,vue3,element-plus,mybatis-plus 1.java后端系统 首先需要学生通过前端注册页面和java后端系统将个人信息写入数据库,包含学号、姓名、班级以及需要爬取网站的相关信息(例如AtCoder账号信…

智谱清言 HTTP调用 + postman使用

官方教程 接口鉴权 非SDK用户鉴权 官方网站 第一步 获取您的 API Key 第二步 使用 JWT 组装 用户端需引入对应 JWT 相关工具类,并按以下方式组装 JWT 中 header、payload 部分 1、header 具体示例 {“alg”:“HS256”,“sign_type”:“SIGN”} alg : 属性表…

批量导入svg文件作为图标使用(vue3)vite-plugin-svg-icons插件的具体应用

目录 需求svg使用简述插件使用简述实现安装插件1、配置vite.config.ts2、src/main.ts引入注册脚本3、写个icon组件4、使用组件 需求 在vue3项目中,需要批量导入某个文件夹内数量不确定的svg文件用来作为图标,开发完成后能够通过增减文件夹内的svg文件&a…

ICLR 2024 | 联邦学习后门攻击的模型关键层

ChatGPT狂飙160天,世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站https://ai.hzytsoft.cn/ 更多资源欢迎关注 联邦学习使多个参与方可以在数据隐私得到保护的情况下训练机器学习模型。但是由于服务器无法…

论文阅读——MVDiffusion

MVDiffusion: Enabling Holistic Multi-view Image Generation with Correspondence-Aware Diffusion 文生图模型 用于根据给定像素到像素对应关系的文本提示生成一致的多视图图像。 MVDiffusion 会在给定任意每个视图文本的情况下合成高分辨率真实感全景图像,或将…

亚信安慧AntDB:开启数据洞察的新视野

AntDB一直秉承着“技术生态”的理念,不断进行技术创新和功能增强,以保持与先进数据库系统的竞争力。作为一款致力于提升数据库处理性能和稳定性的系统,AntDB在技术上始终保持敏锐的洞察力,不断汲取国内外先进技术的精华&#xff0…

Scala大数据开发

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl Scala简述 在此,简要介绍 Scala 的基本信息和情况。 Scala释义 Scala 源自于英语单词scalable,表示可伸缩的、可扩展的含义。 Scala作者 Scala编…