软件设计模式系列之三———工厂方法模式

news2024/12/29 9:37:58

1 模式的定义

工厂方法模式是一种常见的设计模式,属于创建型设计模式之一,它在软件工程中用于对象的创建。该模式的主要思想是将对象的创建过程抽象化,将具体对象的实例化延迟到子类中完成,以便在不同情况下可以创建不同类型的对象,而客户端代码不需要知道实际创建的对象类型。

2 举例说明

在这里插入图片描述

不同公司都生产自己的手机,就符合工厂方法模式。比如小米和华为都是手机制造商,而手机则是产品。每家公司都有自己的生产流程和标准,但它们都需要生产手机以满足市场需求。
工厂方法模式中,每家公司都有一个具体的工厂(小米工厂和华为工厂),这些工厂实现了一个共同的抽象工厂接口。抽象工厂定义了一个方法用于生产手机,但具体的手机生产过程由每家公司的工厂来实现。
客户端代码可以根据需要选择使用小米工厂或华为工厂来生产手机。这种方式下,客户端代码无需关心手机的具体制造过程,只需知道如何与抽象工厂交互即可。
工厂方法模式的优点在于它实现了对象的创建和客户端代码的解耦,使得不同的工厂可以独立扩展,适用于多样化的产品生产场景。小米和华为手机的制造就是一个生动的示例,其中工厂方法模式为不同公司的手机生产提供了一种灵活的、可扩展的解决方案

3 结构

工厂方法模式的结构包括以下几个关键角色:

在这里插入图片描述

  • 抽象工厂接口(Factory):这是工厂方法模式的核心部分,它定义了一个或多个工厂方法的接口,这些方法用于创建具体产品对象。通常,这个接口中会包含多个方法,每个方法用于创建不同类型的产品。客户端代码通过调用这些工厂方法来获取产品对象。
  • 具体工厂类(Concrete Factory):这是实现抽象工厂接口的具体类,每个具体工厂类负责创建一类具体产品。它实现了工厂方法,根据客户端的需求创建具体的产品对象。每个具体工厂类通常对应一个特定的产品族。
  • 抽象产品接口(Product):这个接口定义了产品对象的通用属性和方法,所有具体产品类都必须实现这个接口。客户端代码将与抽象产品接口进行交互,而不直接与具体产品类进行交互。
  • 具体产品类(Concrete Product):这些是实际的产品类,它们实现了抽象产品接口,定义了具体产品的属性和行为。每个具体产品类对应一个具体工厂类。
  • 客户端(Client):客户端代码需要创建产品对象,但它不直接与具体产品类或具体工厂类交互。客户端通过调用抽象工厂接口中的工厂方法来创建产品对象,从而实现了解耦的目的。

工厂方法模式的结构允许在不修改客户端代码的情况下引入新的具体产品类和具体工厂类,从而增加系统的可扩展性。客户端只需要知道抽象工厂接口和抽象产品接口,而不需要关心具体的产品类和工厂类,这使得系统更易于维护和扩展。

总结来说,工厂方法模式的结构包括抽象工厂接口、具体工厂类、抽象产品接口、具体产品类以及客户端。这个模式通过将对象的创建委托给具体工厂类来实现对象的创建和客户端与产品之间的解耦。

4 实现步骤

工厂方法模式的实现步骤通常包括以下几个关键步骤:

  • 定义抽象产品接口(Product):定义一个抽象产品接口,它声明了产品对象的通用属性和方法。所有具体产品类都必须实现这个接口。
  • 创建具体产品类(Concrete Product):实现抽象产品接口的具体产品类。每个具体产品类表示一种具体的产品。
  • 定义抽象工厂接口(Factory):创建一个抽象工厂接口,该接口声明了工厂方法,用于创建产品对象。
  • 创建具体工厂类(Concrete Factory):实现抽象工厂接口的具体工厂类,每个具体工厂类负责创建特定类型的产品。在客户端中使用工厂方法:
  • 客户端代码通过具体工厂类的工厂方法来创建产品对象,而不直接实例化具体产品类。

通过上述步骤,您就可以实现工厂方法模式。这种模式允许客户端根据需要选择合适的具体工厂来创建产品,从而实现了解耦和可扩展性。如果需要添加新的产品类型,只需创建新的具体产品类和对应的具体工厂类,而不需要修改现有的客户端代码。

5 代码实现

以下是使用工厂方法模式实现抽象工厂(AbstractFactory)、具体工厂(XiaomiFactoryHuaweiFactory)、抽象产品(AbstractMobile)和具体产品(XiaomiMobileHuaweiMobile)的Java代码示例:

// 抽象产品接口
interface AbstractMobile {
    void displayInfo();
}

// 具体产品类 - 小米手机
class XiaomiMobile implements AbstractMobile {
    @Override
    public void displayInfo() {
        System.out.println("这是小米手机。");
    }
}

// 具体产品类 - 华为手机
class HuaweiMobile implements AbstractMobile {
    @Override
    public void displayInfo() {
        System.out.println("这是华为手机。");
    }
}

// 抽象工厂接口
interface AbstractFactory {
    AbstractMobile createMobile();
}

// 具体工厂类 - 小米工厂
class XiaomiFactory implements AbstractFactory {
    @Override
    public AbstractMobile createMobile() {
        return new XiaomiMobile();
    }
}

// 具体工厂类 - 华为工厂
class HuaweiFactory implements AbstractFactory {
    @Override
    public AbstractMobile createMobile() {
        return new HuaweiMobile();
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        // 使用具体工厂创建具体产品
        AbstractFactory xiaomiFactory = new XiaomiFactory();
        AbstractMobile xiaomiMobile = xiaomiFactory.createMobile();
        xiaomiMobile.displayInfo();

    AbstractFactory huaweiFactory = new HuaweiFactory();
        AbstractMobile huaweiMobile = huaweiFactory.createMobile();
        huaweiMobile.displayInfo();
    }
}

在这个代码示例中,我们定义了抽象产品接口 AbstractMobile 和两个具体产品类 XiaomiMobileHuaweiMobile。然后,我们定义了抽象工厂接口 AbstractFactory,其中包含了一个工厂方法 createMobile(),用于创建手机产品。

接下来,我们创建了两个具体工厂类 XiaomiFactoryHuaweiFactory,分别实现了 AbstractFactory 接口,并在其中实现了工厂方法,分别用于创建小米手机和华为手机。

最后,在客户端代码中,我们使用不同的具体工厂来创建不同的手机产品,从而实现了工厂方法模式,客户端代码不需要知道具体产品的细节,只需要知道如何使用抽象工厂来创建产品

6 典型应用场景

6.1 数据库驱动程序的创建

在这里插入图片描述

使用工厂方法模式来进行数据库驱动程序创建的场景是在软件开发中需要连接不同类型的数据库(例如MySQL、PostgreSQL、Oracle等)时。通过工厂方法模式,可以将不同数据库的连接对象的创建过程封装在各自的工厂类中,客户端代码无需关心具体的数据库驱动程序实现,只需使用相应的工厂来创建数据库连接对象,从而实现了灵活性和可扩展性,能够轻松地切换和添加新的数据库驱动程序,而不影响现有的代码。这种模式在多数据库支持和数据库连接的抽象化方面非常有用。

6.1 UI控件的创建

使用工厂方法模式进行UI控件创建的场景是在图形用户界面(GUI)开发中。不同操作系统或界面库(如Windows、macOS、Android等)可能使用不同的UI控件(如按钮)。通过工厂方法模式,可以将每种UI控件的创建过程封装在各自的工厂类中,客户端代码无需关心具体的控件实现,只需使用相应的工厂来创建控件对象,从而实现了跨平台和可扩展性,使得应用程序能够在不同的操作系统或界面库下创建合适的UI控件,而不需要重写整个界面代码。这种模式在多平台UI开发和UI组件的抽象化方面非常有用。

6.3 日志记录器

在应用程序中需要记录日志以进行调试、故障排除和性能监测时。不同的日志记录方式(如文件日志、数据库日志、控制台日志等)可能需要使用不同的日志记录器。通过工厂方法模式,可以将每种日志记录器的创建过程封装在各自的工厂类中,客户端代码无需关心具体的日志记录器实现,只需使用相应的工厂来创建日志记录器对象,从而实现了灵活性和可扩展性,使得应用程序可以根据需求选择不同的日志记录方式,而不需要修改主要的应用逻辑。这种模式在日志记录方式的切换和定制化日志记录方面非常有用。

6.4 游戏中不同角色的创建

使用工厂方法模式来创建游戏中不同角色的场景是在游戏开发中。在游戏中,有各种不同类型的角色(如玩家、敌人、道具、NPC等),每个角色都有自己独特的属性和行为。通过工厂方法模式,可以将每种角色的创建过程封装在各自的工厂类中,客户端代码无需关心具体的角色实现,只需使用相应的工厂来创建角色对象,从而实现了游戏角色的动态创建和管理。这种模式在游戏中角色的扩展和多样化方面非常有用,使得游戏开发人员可以轻松地添加新的角色类型,而不需要修改游戏引擎或核心逻辑。

7 优缺点

工厂方法模式是一种常用的设计模式,它具有一些优点和缺点:

优点:

松耦合 :工厂方法模式将对象的创建过程封装在工厂类中,客户端代码与具体产品类解耦。客户端代码只需要关心抽象工厂和产品接口,无需了解具体产品的细节。

可扩展性 :通过添加新的具体工厂类和具体产品类,可以轻松扩展系统以支持新的产品类型,而不需要修改现有的代码。这使得系统更容易维护和扩展。

多态性 :工厂方法模式利用了多态性,使得客户端可以根据需要创建不同类型的产品对象,而无需改变客户端代码。

符合开闭原则 :工厂方法模式遵循开闭原则,对修改关闭,对扩展开放。添加新的产品类型只需要添加新的具体工厂类和具体产品类,而不需要修改现有代码。

缺点:

类的数量增加 :引入工厂方法模式会增加类的数量,每个具体产品类都需要一个对应的具体工厂类。对于一些简单的情况,可能会使代码变得复杂。

复杂性增加 :在有多层继承结构的情况下,可能会引入更多的层次,增加代码的复杂性。

不适用于单例 :工厂方法模式通常用于创建多个对象,不适用于创建单例对象。对于单例模式,通常使用其他模式,如单例模式或者静态工厂方法。

增加代码复杂度 :在简单情况下,使用工厂方法模式可能会增加不必要的复杂性,不如直接实例化对象来得简单。

总之,工厂方法模式在实现对象的创建和客户端代码解耦方面有很多优点,但也需要谨慎使用,根据具体情况来决定是否使用该模式,以确保代码的可维护性和扩展性。

8 类似模式

工厂方法模式、抽象工厂模式和简单工厂模式都是创建型设计模式,用于对象的创建,但它们在关注点和应用场景上存在差异。

简单工厂模式是一种简化对象创建的方法,不是 GoF(Gang of Four)的正式设计模式。简单工厂适用于创建少量的对象,但不符合开闭原则,不支持扩展新的产品类型。

工厂方法模式是一种正式的设计模式,定义了一个创建对象的接口,具体的对象创建延迟到子类中完成。用于创建单一产品等级结构。

抽象工厂模式也是一种正式的设计模式,提供一个接口,用于创建一系列相关或依赖的对象,不需要指定具体的类。每个具体工厂类可以创建一组相关的产品,用于创建多个相关的产品等级结构或整个产品族。

它们都以不同的方式提供了对象创建的灵活性和可扩展性,根据需求选择合适的模式。

9 小结

工厂方法模式是一种常用的设计模式,属于创建型设计模式,其核心思想是将对象的创建延迟到子类中去完成。特别适合在需要创建多个相关但不同类型的对象时,以提高代码的可维护性和可扩展性。它将对象的创建过程进行了抽象,使得客户端代码更加灵活,可以根据需要选择不同的具体工厂来创建对象。

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

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

相关文章

2023-09-12 - 7 搜索排序

1 查询时设置权重 用户可以使用布尔查询将多种查询组合在一起。在默认情况下,这些查询的权重都为1,也就是查询之间都是平等的。有时我们希望某些查询的权重高一些,也就是在其他条件相同的情况下,匹配该查询的文档得分更高。此时应…

高忆管理:震仓什么意思?

震仓是股市、期货商场和商业运营中常见的一个概念。它的本意是指在生意中许多生意同一种证券或产品,然后引起商场的震荡。在详细的情境中,震仓有许多不同的意义。本文将从股市、期货商场和商业运营三个角度解析震仓的意义和效果。 一、股市中的震仓 在股…

RK3568开发笔记(八):开发板烧写buildroot固件(支持hdmi屏),搭建Qt交叉编译开发环境,编译一个Demo,目标板运行Demo测试

若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/132826197 红胖子网络科技博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬…

Map和Set及其实现类详解

目录 一, 搜索 1,传统搜索 2,Map和Set模型 二, Map的使用 1,Map接口的继承及实现图 2,Map接口的使用 3,TreeMap和HashMap的使用和对比 1,TreeMap 代码示例 map中插入的数据按照key进行排序 map中插入的数据必须具有可比较性(或者实现了比较器相关接口) ​map中插入…

鸿蒙应用开发(基础篇)之列表组件

一、简介 在我们常用的手机应用中,经常会见到一些数据列表,如设置页面、通讯录、商品列表等。下图中两个页面都包含列表,“首页”页面中包含两个网格布局,“商城”页面中包含一个商品列表。 上图中的列表中都包含一系列相同宽度的…

XShell7 + Xftp7 + IDEA 打包MapReduce程序到集群运行

参考博客 【MapReduce打包成jar上传到集群运行】http://t.csdn.cn/2gK1d 【Xshell7/Xftp7 解决强制更新问题】http://t.csdn.cn/rxiBG IDEA打包MapReduce程序 这里的打包是打包整个项目,后期等学会怎么打包单个指定的mapreduce程序再来更新博客。 1、编译打包 …

MATLAB入门-程序控制结构

MATLAB入门-程序控制结构 注:本篇文章为课程学习笔记,课程链接为:头歌 if、elseif、else 相比于C语言,这里多了一个end switch、case、otherwise 相比于C语言,这里也多了一个end,默认字符也不一样。 …

智慧公厕建设,要以技术为支撑、体验为目的、业务为驱动

#智慧公厕[话题]# #智慧公厕系统[话题]# #智慧公厕厂家[话题]# #智慧公厕驿站[话题]# 在数字化城市与智慧城市的大力推进下,作为社会重要的生活设施,智慧化的公共厕所的建设变得越来越重要。作为城市的基础部件之一,公厕的智慧化建设需要进行…

实例 | Python 实现 RSA 加解密

大家好,欢迎来到编程教室 ! 前阵子看到一篇英文文章[1],展示了如何用 Python 来实现 RSA 算法。不太熟悉 RSA 的朋友可以看一下一文搞懂 RSA 算法,里面对什么是 RSA,RSA 的数学原理进行了说明,并举了一个简…

平板用的触控笔什么牌子好?开学便宜电容笔推荐

在新学期即将来临之际,你觉得什么样的电容笔才是最好的选择呢?我是一个数码爱好者,有几年以上的使用经验,也知道一些关于电容笔的事情。我觉得,这款苹果原装的电容笔,与普通的电容笔最大的不同之处&#xf…

手把手教你,如何先梳理业务逻辑再写代码

1.业务逻辑与代码 代码是需求逻辑的一种展现形式 需求文档是业务逻辑的一种展现形式,而代码不过是业务逻辑的另一种表现形式;如果逻辑本身有问题,那么它的各种展示形式自然也是错的,所以写代码前应该先思考清楚业务逻辑。 Revi…

【校招VIP】专业课考点之网络存储

考点介绍: cookie、session和localstorage 是目前常用的存储机制,不管是大厂还是中小公司,都会对这个问题有比较高的考察频度,而且有一定的深度和对比分析 专业课考点之网络存储-相关题目及解析内容可点击文章末尾链接查看&#…

为什么C ++在嵌入式系统设计中是C的可行替代品

你是一名。你知道C是适合该工作的语言,尽管有时维护周期可以重复很长时间。有时你会感到that琐,就像在编码自动机一样,反复在结构上创建基本迭代,这些结构与上周或上个月的结构非常相似。 你已经听说过C 作为一种功能强大的语言的…

【AI绘画接口】Midjourney是什么?Midjourney有官方接口吗?

什么是 Midjourney? 随着AI技术的发展,AI聊天、AI绘画都从小众尝鲜逐渐应用到了生产当中。现在市面上的绘画AI并不少,而 Midjourney 是其中最好用的之一。我们只需要输入一些提示词,Midjourney 就能根据输入的提示词自动生成符合…

怎么找回回收站删除的文件?轻松恢复数据,就看这3个方法!

“求助求助!回收站删除的文件还有找回来的机会吗?一不小心就把回收站中的文件删除了,现在不知道该如何是好了,希望热心的网友们可以帮帮我!” 大家都知道,电脑有一个功能叫回收站,系统会将我们删…

代码随想录 -- day49 -- 121. 买卖股票的最佳时机 、122.买卖股票的最佳时机II

121. 买卖股票的最佳时机 动态规划: dp[i][0] 表示第i天持有股票所得最多现金,dp[i][0] 表示第i天持有股票所得最多现金。 第i-1天就持有股票,那么就保持现状,所得现金就是昨天持有股票的所得现金 即:dp[i - 1][0]第…

echarts折线图每段显示不同的颜色

效果图 配置项: zqChartFour: {title: {text: "一天用电量分布",subtext: "纯属虚构",},tooltip: {trigger: "axis",axisPointer: {type: "cross",},},toolbox: {show: true,feature: {saveAsImage: {},},},xAxis: {type:…

Linux 中nc指令的使用总结

nc指令概述用法一:端口扫描用法二:命令行中发送和接收数据用法三:建立双方通信 nc指令概述 nc 是 Linux 系统中的 netcat 命令之简称,它是一个强大的网络工具,可以用于创建 TCP/UDP 套接字连接。常见的其用法模板可定…

目标检测中生成锚框函数详解

将设一张图片,宽和高为2,2 X torch.rand(size(1,3,2,2)) Y generate_anchors(X,sizes[0.75,0.5,0.25],ratios[1,2,0.5])锚框中心点的设置 # 为每个像素可以生成 nm-1个锚框,整个图像生成 wh(nm-1) def generate_anchors(data,sizes,ratios): # 书上的…

重磅预告 |第十二届中国智能产业高峰论坛9月16日在昌开幕,集团董事长李火亮任专题联席主席,出席本次活动

在这个数字化、智能化社会经济高速迭代的时代,每一次技术的进步都预示着一个全新的未来。在此背景下第十二届中国智能产业高峰论坛即将拉开帷幕。9月16日-9月18日高峰论坛在中国南昌举行,拓世科技集团董事长李火亮将亲身出席本次活动,与众多领…