设计模式之工厂模式

文章目录

  • 前言
  • 一、工厂模式的意义和优点
    • 1、解耦创建和使用(Separation of Concerns)
    • 2、 遵循“开闭原则”(Open/Closed Principle)
    • 3、提升代码的可维护性和可读性
    • 4、 减少重复代码(Code Reusability and Reduction of Duplication)
    • 5、 促进对象的管理和控制
    • 6、 便于替换和测试
  • 二、工厂模式的实现方式
    • 1、简单工厂模式 (Simple Factory Pattern)
    • 2、工厂方法模式(Factory Method Pattern)
    • 3、抽象工厂模式(Abstract Factory Pattern)


前言

工厂模式(Factory Pattern)作为一种创建型设计模式,致力于解决对象创建问题,并将对象的创建过程与使用过程分离开来。其核心意义在于提高代码的灵活性、可扩展性与可维护性。通过深入理解其作用和优点,可以更好地在软件开发中应用这一模式。


一、工厂模式的意义和优点

1、解耦创建和使用(Separation of Concerns)

工厂模式将对象的创建逻辑从使用逻辑中解耦。客户端无需知道具体的对象创建过程,只需依赖工厂来获取对象实例。这提升了代码的模块化程度,使得系统中的各部分变得更加独立和容易维护。

示例:在复杂系统中,业务逻辑层和数据访问层的代码可以通过工厂模式进行隔离。业务逻辑层无需关心具体的数据库连接和数据结构,只需通过工厂类获取所需的对象。

2、 遵循“开闭原则”(Open/Closed Principle)

工厂模式有助于遵循SOLID原则中的开闭原则,即对扩展开放,对修改关闭。当需要添加新的产品类时,只需添加新的具体工厂类或修改现有工厂类,而无需更改现有的客户端代码。

示例:在工厂方法模式中,通过创建新的工厂子类来生成新的产品对象,可以在不修改现有代码的情况下扩展系统。

3、提升代码的可维护性和可读性

将对象的创建逻辑集中在工厂类中,使得代码的维护和修改更加集中,这大大提升了代码的可读性和可维护性。开发人员只需查看和修改工厂类,而不是遍布整个系统的对象创建代码。

示例:对于跨模块的对象创建,更新创建逻辑或优化性能只需修改工厂类而非分散在各处的创建代码。

4、 减少重复代码(Code Reusability and Reduction of Duplication)

工厂模式能够减少代码中的重复部分,尤其是在对象创建较为复杂的情况下。统一的创建逻辑避免了冗余代码,有助于代码重用。

示例:创建多个复杂对象实例时,所有实例化的细节由工厂类处理,简化了客户端代码。

5、 促进对象的管理和控制

通过工厂方法,可以在创建对象时注入依赖、进行配置或实施某些约束。这有助于在对象生命周期中更好地进行管理和控制。

示例:在创建数据库连接对象时,可以在工厂方法中统一配置连接池参数,确保每个连接对象的初始化符合系统要求。

6、 便于替换和测试

工厂模式使得替换和测试变得更加方便。通过工厂方法,较容易实现依赖注入 (Dependency Injection) 和控制反转(Inversion of Control),从而提高测试的可控性和灵活性。

示例:在单元测试中,可以使用模拟(mock)的工厂类来提供伪对象,从而隔离对外部资源的依赖。

二、工厂模式的实现方式

1、简单工厂模式 (Simple Factory Pattern)

简单工厂模式,也称为静态工厂方法模式,是用一个工厂类来创建对象。这种方式非常简单,但是在增加新的产品类时需要修改工厂类,违背了开闭原则(Open-Closed Principle)。
假设我们要创建不同类型的汽车对象:

// 汽车接口
public interface Car {void drive();
}// 具体的汽车实现类
public class Sedan implements Car {@Overridepublic void drive() {System.out.println("Driving a sedan...");}
}public class SUV implements Car {@Overridepublic void drive() {System.out.println("Driving an SUV...");}
}// 简单工厂类
public class CarFactory {public static Car createCar(String type) {switch (type) {case "sedan":return new Sedan();case "suv":return new SUV();default:throw new IllegalArgumentException("Unknown car type.");}}
}// 客户端代码
public class Main {public static void main(String[] args) {Car sedan = CarFactory.createCar("sedan");sedan.drive();Car suv = CarFactory.createCar("suv");suv.drive();}
}

2、工厂方法模式(Factory Method Pattern)

工厂方法模式通过定义一个创建对象的接口,让子类决定实例化哪个类。这种模式让一个类的实例化延迟到其子类。
以创建不同类型的汽车为例:

// 汽车接口
public interface Car {void drive();
}// 具体的汽车实现类
public class Sedan implements Car {@Overridepublic void drive() {System.out.println("Driving a sedan...");}
}public class SUV implements Car {@Overridepublic void drive() {System.out.println("Driving an SUV...");}
}// 工厂方法接口
public interface CarFactory {Car createCar();
}// 具体的工厂实现类
public class SedanFactory implements CarFactory {@Overridepublic Car createCar() {return new Sedan();}
}public class SUVFactory implements CarFactory {@Overridepublic Car createCar() {return new SUV();}
}// 客户端代码
public class Main {public static void main(String[] args) {CarFactory sedanFactory = new SedanFactory();Car sedan = sedanFactory.createCar();sedan.drive();CarFactory suvFactory = new SUVFactory();Car suv = suvFactory.createCar();suv.drive();}
}

3、抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。这种模式可以更好地支持扩展,且更加复杂和灵活。
我们不再只创建某种汽车,而是创建不同品牌的工厂来生产不同类型的汽车。

// 汽车接口
public interface Car {void drive();
}// 具体的汽车实现类
public class Sedan implements Car {@Overridepublic void drive() {System.out.println("Driving a sedan...");}
}public class SUV implements Car {@Overridepublic void drive() {System.out.println("Driving an SUV...");}
}// 抽象工厂接口
public interface CarFactory {Car createSedan();Car createSUV();
}// 具体的工厂实现类
public class FordFactory implements CarFactory {@Overridepublic Car createSedan() {return new Sedan() {@Overridepublic void drive() {System.out.println("Driving a Ford sedan...");}};}@Overridepublic Car createSUV() {return new SUV() {@Overridepublic void drive() {System.out.println("Driving a Ford SUV...");}};}
}public class ToyotaFactory implements CarFactory {@Overridepublic Car createSedan() {return new Sedan() {@Overridepublic void drive() {System.out.println("Driving a Toyota sedan...");}};}@Overridepublic Car createSUV() {return new SUV() {@Overridepublic void drive() {System.out.println("Driving a Toyota SUV...");}};}
}// 客户端代码
public class Main {public static void main(String[] args) {CarFactory fordFactory = new FordFactory();Car fordSedan = fordFactory.createSedan();fordSedan.drive();CarFactory toyotaFactory = new ToyotaFactory();Car toyotaSUV = toyotaFactory.createSUV();toyotaSUV.drive();}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VB6.0 显示越南语字符

近期接到客户咨询,说是VB6.0写软件界面上显示越南语乱码,需要看看怎样解决。 我在自己电脑上也试了下,确实显示越南语结果是乱码。编辑器里乱码,运行起来界面上也是乱码。 经过一天的折腾,算是解决了问题&#xff0c…

理解C++中的右值引用

右值引用,顾名思义,就是对一个右值进行引用,或者说给右值一个别名。右值引用的规则和左值一用一模一样,都是对一个值或者对象起个别名。 1. 右值引用和左值引用一样,在定义的同时必须立即赋值,如果不立即赋…

unity.NavMesh Agent

这张图片展示的是Unity中 NavMesh Agent 组件的参数设置。NavMesh Agent 是Unity中用于实现角色自动寻路和移动的组件。下面我会通俗易懂地讲解这些参数的作用: 1. Agent Type(代理类型) 作用:定义代理的类型,比如是人…

83,【7】BUUCTF WEB [MRCTF2020]你传你[特殊字符]呢

进入靶场 图片上这个人和另一道题上的人长得好像 54,【4】BUUCTF WEB GYCTF2020Ezsqli-CSDN博客 让我们上传文件 桌面有啥传啥 /var/www/html/upload/344434f245b7ac3a4fae0a6342d1f94a/123.php.jpg 成功后我就去用蚁剑连了,连不上 看了别的wp知需要…

自签证书的dockerfile中from命令无法拉取镜像而docker的pull命令能拉取镜像

问题现象: docker pull images拉取镜像正常 dockerfile中的from命令拉取镜像就会报出证书错误。报错信息如下: [bjxtbwj-kvm-test-jenkins-6-243 ceshi_dockerfile]$ docker build . [] Building 0.4s (3/3) FINISHED …

在小红书挖掘信息的实践之旅(第一部分)

摘要 在信息爆炸时代,小红书承载大量用户真实生活分享,蕴含未挖掘价值。作者因日常观察到朋友常依赖小红书经验分享,决定尝试挖掘其中信息。在实践初期,受 DeepSeek 建议启发,确定 “以关键词为线索,层层递…

智慧消防营区一体化安全管控 2024 年度深度剖析与展望

在 2024 年,智慧消防营区一体化安全管控领域取得了令人瞩目的进展,成为保障营区安全稳定运行的关键力量。这一年,行业在政策驱动、技术创新应用、实践成果及合作交流等方面呈现出多元且深刻的发展态势,同时也面临着一系列亟待解决…

粒子群算法 笔记 数学建模

引入: 如何找到全局最大值:如果只是贪心的话,容易被局部最大解锁定 方法有:盲目搜索,启发式搜索 盲目搜索:枚举法和蒙特卡洛模拟,但是样例太多花费巨量时间 所以启发式算法就来了,通过经验和规…

从ai产品推荐到利用cursor快速掌握一个开源项目再到langchain手搓一个Text2Sql agent

目录 0. 经验分享:产品推荐 1. 经验分享:提示词优化 2. 经验分享:使用cursor 阅读一篇文章 3. 经验分享:使用cursor 阅读一个完全陌生的开源项目 4. 经验分享:手搓一个text2sql agent (使用langchain l…

14-6-1C++STL的list

(一)list容器的基本概念 list容器简介: 1.list是一个双向链表容器,可高效地进行插入删除元素 2.list不可以随机存取元素,所以不支持at.(pos)函数与[ ]操作符 (二)list容器头部和尾部的操作 list对象的默…

Couchbase UI: Dashboard

以下是 Couchbase UI Dashboard 页面详细介绍,包括页面布局和功能说明,帮助你更好地理解和使用。 1. 首页(Overview) 功能:提供集群的整体健康状态和性能摘要 集群状态 节点健康状况:绿色(正…

【WebRTC - STUN/TURN服务 - COTURN配置】

在WebRTC中,对于通信的两端不在同一个局域网的情况下,通信两端往往无法P2P直接连接,需要一个TURN中继服务,而中继服务可以选用 COTURN 构建。 注:COTURN 是一个开源的 TURN(Traversal Using Relays around…

基于OSAL的嵌入式裸机事件驱动框架——整体架构调度机制

参考B站up主【架构分析】嵌入式祼机事件驱动框架 感谢大佬分享 任务ID : TASK_XXX TASK_XXX 在系统中每个任务的ID是唯一的,范围是 0 to 0xFFFE,0xFFFF保留为SYS_TSK_INIT。 同时任务ID的大小也充当任务调度的优先级,ID越大&#…

【测试】UI自动化测试

长期更新,建议关注收藏点赞! 目录 概论WEB环境搭建Selenium元素定位 APPAppium 概论 user interface UI 使用工具和代码执行用例。 什么样的项目需要自动化? 需要回归测试、自动化的功能模块需求变更不频繁、项目周期长(功能测试…

【随手笔记】FFT资料整理

&#xff08;一&#xff09;结果验证 函数波形示例1 #define Fs 44800 #define NPT 256 void InitBufInArray() {int i 0;float fx 0;for(i0; i<NPT; i){// fx 1500 * sin(2*PI * i * 350.0 / Fs) // 2700 * sin(2*PI * i * 8400.0 / Fs) // 4000 * sin(2*P…

Airflow:Airflow子流程应用实践

Apache Airflow是一个强大的开源平台&#xff0c;用于以编程方式编写、调度和监控工作流。它的一个强大功能是使用子DAG&#xff08;子有向无环图&#xff09;创建复杂工作流的能力&#xff0c;子DAG本质上是在父DAG中更小的嵌套DAG。在这篇博文中&#xff0c;我们将深入探讨su…

狗狗能吃萝卜吗?

各位铲屎官们&#xff0c;今天咱们来聊聊一个超实用的话题&#xff1a;狗狗能吃萝卜吗&#xff1f;很多新手铲屎官可能会觉得萝卜营养丰富&#xff0c;想给狗狗也尝尝鲜&#xff0c;但其实这里面大有讲究&#xff01; 狗狗可以吃萝卜&#xff0c;但要注意方法 首先&#xff0c…

Excel制作合同到期自动提醒!

大家好&#xff0c;我是小鱼。 今天分享一下如何利用Excel制作合同到期提醒表&#xff0c;实现Excel表格自动计算合同到期日和天数&#xff0c;根据合同状态和到期天数自动填充颜色提醒&#xff0c;超实用。先看一下效果&#xff0c;已经到期的合同会自动被填充为红色&#xf…

Python Flask教程

一、前言 Flask是一个用Python编写的轻量级的Web应用框架。 Flask基于WSGI&#xff08;Web Server Gateway Interface&#xff09;和 Jinja2 模板引擎&#xff0c;旨在帮助开发者快速、简便地创建 Web 应用。 Flask 被称为"微框架"&#xff0c;因为它使用简单的核…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.10 文本数据炼金术:从CSV到结构化数组

1.10 《文本数据炼金术&#xff1a;从CSV到结构化数组》 目录 #mermaid-svg-TNkACjzvaSXnULaB {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-TNkACjzvaSXnULaB .error-icon{fill:#552222;}#mermaid-svg-TNkACjzva…