设计模式-01简单工厂模式详解 详细代码对比

news2025/1/11 2:21:18

目录

  • ChatGpt问答
    • 原生代码
    • 简单工厂模式代码
  • 简单工厂模式(Simple Factory Pattern)
  • 新增boat 对比两种方法
    • 原生代码
    • 为什么使用强制转换?
    • 简单工厂模式
  • 简单工厂方法总结
    • 与原生代码的区别:
    • 优点:
    • 缺点:
  • 参考

本文将介绍什么事简单工厂模式,为什么要使用这个模式?比起原生代码它是如何降低代码的耦合度的,以及详细的代码对比,结合ChatGPT的问答进行讲解,也是自己学习的记录,有不对的地方请指正。

ChatGpt问答

Q:Give an example to illustrate the benefits of reducing the coupling
of the simple factory model in java, which is best reflected in code

举个例子来说明java中简单工厂模式减少耦合的好处,在代码中最能体现

Certainly! Let’s illustrate the benefits of reducing coupling by using a simple factory model in Java. We’ll start with a coupled implementation and then refactor it to reduce coupling.

当然! 让我们说明一下在 Java 中使用简单工厂模型来减少耦合的好处。 我们将从耦合实现开始,然后重构它以减少耦合。

Coupled Implementation (High Coupling):

Consider a simple factory that produces different types of vehicles (e.g., cars and bicycles) based on a provided type. In this coupled example, the factory method has a high level of coupling with the concrete vehicle classes.

考虑一个简单的工厂,它根据提供的类型生产不同类型的车辆(例如汽车和自行车)。 在这个耦合示例中,工厂方法与具体车辆类具有高度耦合。

原生代码

class VehicleFactory {
    public Vehicle createVehicle(String type) {
        if ("car".equalsIgnoreCase(type)) {
            return new Car();
        } else if ("bicycle".equalsIgnoreCase(type)) {
            return new Bicycle();
        } else {
            throw new IllegalArgumentException("Invalid vehicle type");
        }
    }
}

class Car {
    void start() {
        System.out.println("Car started.");
    }
}

class Bicycle {
    void start() {
        System.out.println("Bicycle started.");
    }
}

public class Main {
    public static void main(String[] args) {
        VehicleFactory factory = new VehicleFactory();
        
        Vehicle vehicle1 = factory.createVehicle("car");
        vehicle1.start(); // Output: Car started.
        
        Vehicle vehicle2 = factory.createVehicle("bicycle");
        vehicle2.start(); // Output: Bicycle started.
    }
}

In this example, the VehicleFactory class has high coupling because it directly creates instances of Car and Bicycle. If we need to add more types of vehicles in the future, we would need to modify the factory method, resulting in increased coupling and reduced flexibility.

在这个例子中,VehicleFactory类具有高耦合性,因为它直接创建CarBicycle的实例。 如果以后需要增加更多类型的车辆,就需要修改工厂方法,导致耦合性增加,灵活性降低。

简单工厂模式代码

Reduced Coupling Implementation (Low Coupling):

To reduce coupling, we can use interfaces and abstract classes to define a common contract for all vehicles. This way, the factory method doesn’t need to know the concrete classes of vehicles.

interface Vehicle {
    void start();
}

class Car implements Vehicle {
    public void start() {
        System.out.println("Car started.");
    }
}

class Bicycle implements Vehicle {
    public void start() {
        System.out.println("Bicycle started.");
    }
}

class VehicleFactory {
    public Vehicle createVehicle(String type) {
        if ("car".equalsIgnoreCase(type)) {
            return new Car();
        } else if ("bicycle".equalsIgnoreCase(type)) {
            return new Bicycle();
        } else {
            throw new IllegalArgumentException("Invalid vehicle type");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        VehicleFactory factory = new VehicleFactory();
        
        Vehicle vehicle1 = factory.createVehicle("car");
        vehicle1.start(); // Output: Car started.
        
        Vehicle vehicle2 = factory.createVehicle("bicycle");
        vehicle2.start(); // Output: Bicycle started.
    }
}

In this refactored example, we’ve introduced an interface Vehicle, which both Car and Bicycle implement. The VehicleFactory now returns instances of the Vehicle interface instead of concrete classes. This reduces coupling because the factory method doesn’t depend on specific implementations, making it easier to extend the system with new types of vehicles without modifying existing code.

在这个重构的示例中,我们引入了一个“Vehicle”接口,“Car”和“Bicycle”都实现了该接口。 “VehicleFactory”现在返回“Vehicle”接口的实例,而不是具体类。 这减少了耦合,因为工厂方法不依赖于特定的实现,从而可以更轻松地使用新型车辆扩展系统,而无需修改现有代码。

简单工厂模式(Simple Factory Pattern)

是一种创建型设计模式,它提供了一种简单的方法来创建对象,而不需要直接暴露对象的创建逻辑给客户端。

简单工厂模式又称静态工厂方法模式。它存在的目的很简单:定义一个用于创建对象的接口。
组成结构:

  1. 工厂类角色(Creator):这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。

  2. 抽象产品角色(Product):它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。

  3. 具体产品角色(ConcreteProduct):工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。

用类图表示它们之间的关系
在这里插入图片描述
抽象产品角色–Vehicle 交通工具
具体产品角色 – Car、Bicycle
工厂类角色–VehicleFactory

新增boat 对比两种方法

原生代码

Certainly! In a high coupling approach, you would directly create instances of vehicle classes within the factory method, which can lead to tight dependencies between the factory and the concrete vehicle classes. Here’s an example of a high coupling approach:

当然! 在高耦合方法中,您将直接在工厂方法中创建车辆类的实例,这可能导致工厂和具体车辆类之间的紧密依赖关系。 这是一个高耦合方法的示例:

class Car {
    void start() {
        System.out.println("Car started.");
    }
}

class Bicycle {
    void start() {
        System.out.println("Bicycle started.");
    }
}

class Boat {
    void start() {
        System.out.println("Boat started.");
    }
}

class VehicleFactory {
    public Object createVehicle(String type) {
        if ("car".equalsIgnoreCase(type)) {
            return new Car();
        } else if ("bicycle".equalsIgnoreCase(type)) {
            return new Bicycle();
        } else if ("boat".equalsIgnoreCase(type)) {
            return new Boat();
        } else {
            throw new IllegalArgumentException("Invalid vehicle type");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        VehicleFactory factory = new VehicleFactory();

        Car car = (Car) factory.createVehicle("car");
        car.start(); // Output: Car started.

        Bicycle bicycle = (Bicycle) factory.createVehicle("bicycle");
        bicycle.start(); // Output: Bicycle started.

        Boat boat = (Boat) factory.createVehicle("boat");
        boat.start(); // Output: Boat started.
    }
}

In this high coupling approach:

  1. Each vehicle class (Car, Bicycle, Boat) is directly instantiated within the createVehicle method of the VehicleFactory.
  2. To use a specific vehicle, you need to cast the object returned by the factory to the corresponding vehicle class (Car, Bicycle, Boat).
  3. Adding a new type of vehicle would require modifying the VehicleFactory to create that vehicle type directly.

在这种高耦合方法中:

  1. 每个车辆类(“Car”、“Bicycle”、“Boat”)都直接在“VehicleFactory”的“createVehicle”方法中实例化。
  2. 要使用特定的车辆,需要将工厂返回的对象转换为相应的车辆类(CarBicycleBoat)。
  3. 添加新类型的车辆需要修改 VehicleFactory 以直接创建该车辆类型。

High coupling can make the code less flexible and harder to maintain because any changes to the factory method or the concrete vehicle classes may affect other parts of the code that rely on them. It’s generally a best practice to reduce coupling and use interfaces or abstract classes to achieve better flexibility and maintainability.

高耦合会使代码不太灵活且难以维护,因为对工厂方法或具体车辆类的任何更改都可能会影响依赖它们的代码的其他部分。 通常,最佳实践是减少耦合并使用接口或抽象类来实现更好的灵活性和可维护性。

为什么使用强制转换?

Car car = (Car) factory.createVehicle(“car”)

In the high coupling approach I provided earlier, you are correct that type casting is required when you retrieve the created objects from the factory. This is a limitation of high coupling because you’re directly creating instances of specific classes within the factory method. Let me explain this in more detail:

In the createVehicle method of the VehicleFactory, the factory creates instances of Car, Bicycle, or Boat based on the type parameter.

Since the createVehicle method is declared to return an Object, when you retrieve the created object, it’s treated as an Object reference.

To use the specific functionality of a Car, for example, you need to cast the Object reference back to Car to access Car-specific methods like start.

This type casting introduces potential issues because if you provide the wrong type for the type parameter or if you introduce a new vehicle type in the future, you might get runtime errors (ClassCastException) if the casting doesn’t match the actual type.

In contrast, a low coupling approach, as demonstrated in the previous example, uses interfaces or abstract classes to create a common contract for all vehicles. This way, you can avoid type casting and handle all vehicles uniformly by relying on the common interface. It provides better flexibility, maintainability, and type safety, as you don’t need to cast objects to specific types when using them.

在我之前提供的高耦合方法中,当您从工厂检索创建的对象时,需要进行类型转换,这是正确的。 这是高耦合的限制,因为您是在工厂方法中直接创建特定类的实例。 让我更详细地解释一下:

在 VehicleFactory 的 createVehicle 方法中,工厂根据类型参数创建 Car、Bicycle 或 Boat 的实例。

由于 createVehicle 方法被声明为返回一个对象,因此当您检索创建的对象时,它将被视为对象引用。

例如,要使用汽车的特定功能,您需要将对象引用强制转换回汽车以访问汽车特定的方法,例如启动。

这种类型转换会带来潜在的问题,因为如果您为类型参数提供了错误的类型,或者如果您将来引入新的车辆类型,并且转换与实际类型不匹配,则可能会出现运行时错误 (ClassCastException)。

相反,低耦合方法(如前面的示例所示)使用接口或抽象类为所有车辆创建通用契约。 这样,您可以避免类型转换并依靠通用接口统一处理所有车辆。 它提供了更好的灵活性、可维护性和类型安全性,因为您在使用对象时不需要将对象强制转换为特定类型。

简单工厂模式

Q:show me High Coupling method

Certainly! Let’s add a new Boat vehicle to the existing code. We’ll follow the same approach of using an interface for Boat and updating the factory method to create Boat instances without modifying the existing code.

当然! 让我们在现有代码中添加一个新的“Boat”车辆。 我们将遵循相同的方法,使用“Boat”接口并更新工厂方法来创建“Boat”实例,而无需修改现有代码。

Adding a Boat Vehicle (Low Coupling):

interface Vehicle {
    void start();
}

class Car implements Vehicle {
    public void start() {
        System.out.println("Car started.");
    }
}

class Bicycle implements Vehicle {
    public void start() {
        System.out.println("Bicycle started.");
    }
}

class Boat implements Vehicle {
    public void start() {
        System.out.println("Boat started.");
    }
}

class VehicleFactory {
    public Vehicle createVehicle(String type) {
        if ("car".equalsIgnoreCase(type)) {
            return new Car();
        } else if ("bicycle".equalsIgnoreCase(type)) {
            return new Bicycle();
        } else if ("boat".equalsIgnoreCase(type)) {
            return new Boat();
        } else {
            throw new IllegalArgumentException("Invalid vehicle type");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        VehicleFactory factory = new VehicleFactory();

        Vehicle vehicle1 = factory.createVehicle("car");
        vehicle1.start(); // Output: Car started.

        Vehicle vehicle2 = factory.createVehicle("bicycle");
        vehicle2.start(); // Output: Bicycle started.

        Vehicle vehicle3 = factory.createVehicle("boat");
        vehicle3.start(); // Output: Boat started.
    }
}

In this updated code, we’ve introduced a new Boat class that implements the Vehicle interface. The VehicleFactory has been updated to handle the creation of Boat instances when “boat” is passed as the type. This allows us to add a new type of vehicle (in this case, a boat) without modifying the existing code for the factory or the other vehicles. This demonstrates the flexibility and low coupling achieved by using interfaces and an abstract factory approach.

在此更新的代码中,我们引入了一个新的“Boat”类,它实现了“Vehicle”接口。 “VehicleFactory”已更新,可以在“boat”作为类型传递时处理“Boat”实例的创建。 这使我们能够添加一种新型车辆(在本例中为船),而无需修改工厂或其他车辆的现有代码。 这展示了通过使用接口和抽象工厂方法实现的灵活性和低耦合。

简单工厂方法总结

与原生代码的区别:

从三个维度来说明:
抽象产品角色–Vehicle 交通工具
具体产品角色 – Car、Bicycle
工厂类角色–VehicleFactory

1 简单工厂模式中抽象产品角色Vehicle 使用interface,原生代码是class
2 简单工厂模式中具体产品角色Car,需要实现接口,原生代码为单独类
3 简单工厂模式中具体工厂类角色–VehicleFactory 返回对象是Vehicle 接口,原生代码的返回对象是Object

优点:

  • 将对象的创建逻辑集中在工厂类中,降低了客户端的复杂度。
  • 隐藏了创建对象的细节,客户端只需要关心需要创建何种对象,无需关心对象是如何创建的。
    可以通过修改工厂类来轻松添加新的产品类

缺点:

  • 如果产品的类太多,会导致工厂类中的代码变得很复杂,难以维护。
  • 添加新产品时,需要修改工厂类,也就是会在OperationFactory类中新增case语句,这违背了开闭原则。

总体而言,简单工厂模式适用于创建对象的逻辑相对简单,且产品类的数量较少的场景。对于更复杂的对象创建和对象之间的依赖关系,可以考虑使用其他创建型设计模式,如工厂方法模式或抽象工厂模式。

参考

1 设计模式-01.简单工厂方法https://juejin.cn/post/7267091509953855543

2 JAVA设计模式(三) – 工厂模式
https://juejin.cn/post/7257441765976162361?searchId=202309061335355A323BC0D43AD67B950D#heading-0

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

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

相关文章

golang指针的学习笔记

package main // 声音文件所在的包,每个go文件必须有归属的包 import ("fmt" )// 引入程序中需要用的包,为了使用包下的函数,比如:Printin// 字符类型使用 func main(){ // 基本数据类型,变量存的就是值&am…

做tiktok怎么运营?

一、揭开tiktok的神秘面纱 说到tiktok,你可能想到的是那些精彩的短视频,以及那些在几秒钟内就能吸引无数粉丝的创作者。然而,tiktok的魅力远不止于此。这个全球最受欢迎的短视频社交平台,正以惊人的速度改变着社交媒体的面貌。 二…

【IR】Vision-Language Tracking

调研:视觉-语言跟踪 0x01 Transformer vision-language tracking via proxy token guided cross-modal fusion, PRL2023AbstractIntroductionContribution效果Conclusion 0x02 Divert More Attention to Vision-Language Object Tracking, NeurIPS2022AbstractIntro…

起飞!Python 3.11的10个高效新特性

性能有巨大的提升是Python 3.11的一个重要的改进,除此以外Python 3.11还有增加了许多新的特性。在本文中我们将介绍Python 3.11新特性,通过代码示例演示这些技巧如何提高生产力并优化代码。 1、模式匹配 Python 3.11引入了模式匹配,可以简化…

OpenAI 函数调用教程

推荐:使用 NSDT场景编辑器 快速搭建3D应用场景 什么是OpenAI函数调用? OpenAI API 非常擅长以系统的方式生成响应。只需几行代码即可管理提示、优化模型输出以及执行、生成和语言应用程序。 即使有这么多好东西,OpenAI API对开发人员和工程…

【双指针】移动零

双指针-移动零 283. 移动零 - 力扣(LeetCode) 题目描述 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 示例 1…

03-JVM内存模型剖析与优化

1. JDK体系结构 2. Java语言的跨平台特性 3. JVM整体结构及内存模型 补充一个问题: 在minor gc过程中对象挪动后,引用如何修改? 对象在堆内部挪动的过程其实是复制,原有区域对象还在,一般不直接清理,JVM内部…

【C++基础】类与对象(上):访问限定符、类作用域、类实例化、类对象模型、this指针

​👻内容专栏: C/C编程 🐨本文概括: C基础语法。访问限定符、类作用域、类实例化、类对象模型、this指针等。 🐼本文作者: 阿四啊 🐸发布时间:2023.9.6 面向过程和面向对象初识 C语…

【网络爬虫笔记】爬虫Robots协议语法详解

Robots协议是指一个被称为Robots Exclusion Protocol的协议。该协议的主要功能是向网络蜘蛛、机器人等搜索引擎爬虫提供一个标准的访问控制机制,告诉它们哪些页面可以被抓取,哪些页面不可以被抓取。本文将进行爬虫Robots协议语法详解,同时提供…

MQ 消费者和队列对应关系

参考 Consumer and Consumer Group Load Balancing https://rocketmq.apache.org/docs/4.x/consumer/01concept2 旧版本MQ结论 消费者应用和topic队列一对多的关系。 (一个消费组consumer group里,一个消费者应用可以消费多个队列的消息。一个队列的消…

Podman安装与使用

1.Podman简介 Podman是一个无守护进程的容器引擎,用于在Linux系统上开发、管理和运行OCI容器。 Podman的主要功能包括: 创建和管理容器:Podman可以创建、启动、停止和删除容器,以及管理容器的生命周期。容器镜像管理&#xff1…

华为云云服务器评测|云耀云服务器L实例快速部署MySQL使用指南

文章目录 前言云耀云服务器L实例介绍什么是云耀云服务器L实例?产品优势智能不卡顿价优随心用上手更简单管理更省心 快速购买查看优惠卷购买 安装MySQL重置密码安装更新apt的软件源列表安装MySQL 设置用户名、密码、权限配置安全组 总结 前言 哈喽大家好&#xff0c…

lumion电脑速度太慢怎么办?还不是试试云电脑高效上云设计

在设计与渲染领域,Lumion是一款广受欢迎的3D软件,然而,使用本地电脑进行Lumion设计和渲染存在电脑卡顿崩溃,导致效率慢问题。本文将介绍Lumion设计师使用云电脑的优势,以及如何利用云电脑提高创作效率、释放无限创意。…

李宏毅-21-hw3:对11种食物进行分类-CNN

一、代码慢慢阅读理解总结内化: 1.关于torch.nn.covd2d()的参数含义、具体用法、功能: (1)参数含义: 注意,里面的“padding”参数:《both》side所以是上下左右《四》边都会加一个padding数量…

Support for password authentication was removed on August 13, 2021 解决方案

打开你的github,Setting 点击Developer settings。 点击generate new token 按照需要选择scope 生成token,以后复制下来。 给git设置token样式的remote url git remote set-url origin https://你的tokengithub.com/你的git用户名/仓库名称.git然后就可…

MySQL 连接查询和存储过程

一、连接查询 mysql的连接查询,通常都是将来自两个或多个表的记录行结合起来,基于这些表之间的共同字段,进行数据的拼接 首先,要确定一个主表作为结果集,然后将其它表的行有选择性的连接到选定的主表结果上&#xff…

算法训练day41|动态规划 part03(LeetCode343. 整数拆分、96.不同的二叉搜索树)

文章目录 343. 整数拆分思路分析代码实现 96.不同的二叉搜索树思路分析代码实现 343. 整数拆分 题目链接🔥🔥 给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。 示例 1: …

【2023研电赛】安谋科技企业命题二等奖:基于R329的AI交互早教机器人

本文为2023年第十八届中国研究生电子设计竞赛安谋科技企业命题二等奖分享,参加极术社区的【有奖活动】分享2023研电赛作品扩大影响力,更有丰富电子礼品等你来领!,分享2023研电赛作品扩大影响力,更有丰富电子礼品等你来…

intellij idea如何查看项目maven依赖关系图

文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。 1、打开maven项目依赖 打开后的效果图 2、选择缩放 可以选择1:1 缩放、…

多通道振弦数据记录仪应用桥梁安全监测的解决方案

多通道振弦数据记录仪应用桥梁安全监测的解决方案 城市化进程的加快和交通运输的发展,桥梁作为连接城市的重要交通工具,其安全性也变得越来越重要。为了保证桥梁的安全性,需要进行定期的监测和维护。其中,多通道振弦数据记录仪是…