设计模式(工厂方法-Factory Method)结构|原理|优缺点|场景|示例

目录

        设计模式(分类)        设计模式(六大原则)   

    创建型

        工厂方法         抽象工厂模式        单例模式        建造者模式        

设计模式中的工厂方法(Factory Method)是一种创建型模式,它提供了一种创建对象的灵活方式,通过将对象的创建过程封装在子类中来实现对象的创建延迟。工厂方法模式的核心在于定义一个用于创建对象的接口(或抽象类),并允许子类决定实例化哪个类的对象。以下是对工厂方法模式的详细说明:

模式结构

工厂方法模式通常包含以下角色:

  1. 抽象产品(Product):定义了一个产品的接口,是所有具体产品类的公共父类或接口,声明了产品的通用行为。

  2. 具体产品(Concrete Product):实现了抽象产品的接口,是工厂方法所创建的对象的具体类型。可以有多个具体产品类,每个类对应一种具体产品。

  3. 抽象工厂(Creator):定义了一个创建产品对象的接口,声明了一个创建产品的工厂方法。该方法通常返回抽象产品类型,以便调用者可以使用统一的方式处理各种具体产品。

  4. 具体工厂(Concrete Creator):实现了抽象工厂接口,提供了创建具体产品对象的实现。每一个具体工厂类对应一种具体产品类型,通过重写工厂方法来创建对应的具体产品对象。

工作原理

  • 客户端:需要创建对象时,不直接实例化具体产品类,而是通过调用具体工厂类的工厂方法来获取产品对象。
  • 具体工厂:负责实现工厂方法,该方法根据具体工厂的类型返回相应具体产品类型的实例。具体工厂隐藏了创建产品的具体细节,客户端只需关心所需产品的类型,无需了解创建过程。
  • 抽象产品:作为产品对象的通用接口,为客户端提供统一的操作入口,使得客户端可以使用抽象产品类型的引用来处理具体产品对象,无需关心实际使用的是哪种具体产品。

优缺点

优点
  • 封装性:将对象的创建过程封装在工厂类中,客户端无需关心对象的具体创建过程,只需知道所需产品的类型即可。
  • 灵活性:通过增加新的具体工厂和具体产品类,可以很容易地扩展系统以支持新的产品类型,符合“开闭原则”。
  • 解耦:客户端与具体产品类解耦,只需要和抽象产品以及具体工厂打交道,降低了系统的耦合度。
  • 代码结构清晰:通过工厂方法模式,可以将产品类的实例化代码集中在一起,使得代码结构更加清晰,易于维护。
缺点
  • 类的层级结构增加:引入了额外的抽象层和具体工厂类,可能导致类的层级结构变得复杂。
  • 增加系统的理解与设计难度:对于不熟悉工厂方法模式的开发者,可能需要花费更多时间理解系统的设计和实现。
  • 每次新增产品时都需要添加新的具体工厂:如果产品种类繁多,可能会导致具体工厂类数量的增长。

适用场景

  • 对象创建过程比较复杂:当创建对象涉及大量初始化工作,或者需要依赖具体环境、条件来确定创建何种对象时,工厂方法模式可以将这些复杂性封装在工厂类中。
  • 系统需要支持多种产品类型:如果有多种不同类型的产品需要创建,并且希望在不修改客户端代码的情况下引入新产品,工厂方法模式可以很好地适应这种需求。
  • 隔离直接创建对象的责任:如果不想让客户端直接接触对象创建的细节,或者需要将对象的创建过程与使用过程分离,可以使用工厂方法模式。

代码示例(以Java为例)

// 抽象产品
public interface Car {void drive();
}// 具体产品A
public class SportsCar implements Car {@Overridepublic void drive() {System.out.println("Driving a sports car.");}
}// 具体产品B
public class SedanCar implements Car {@Overridepublic void drive() {System.out.println("Driving a sedan car.");}
}// 抽象工厂
public abstract class CarFactory {public abstract Car createCar();
}// 具体工厂A
public class SportsCarFactory extends CarFactory {@Overridepublic Car createCar() {return new SportsCar();}
}// 具体工厂B
public class SedanCarFactory extends CarFactory {@Overridepublic Car createCar() {return new SedanCar();}
}// 客户端代码
public class Client {public static void main(String[] args) {CarFactory factory = new SportsCarFactory(); // 或者 new SedanCarFactory()Car car = factory.createCar();car.drive();}
}//在这个例子中,客户端通过调用具体工厂(如SportsCarFactory或SedanCarFactory)的createCar()方法来获取所需的Car对象。
//具体创建哪种类型的Car对象由具体工厂决定,客户端无需知道具体的创建细节,只需与Car接口和工厂类交互。这样,系统在不修改现有代码的情况下就能轻易地添加新的汽车类型和对应的工厂类,实现了良好的扩展性

代码示例(以Python为例)

在这个Python示例中:

  • Animal类作为抽象产品,定义了动物的基本属性(如name)和抽象方法make_sound(),要求子类必须实现该方法。
  • DogCat类是具体产品,它们继承自Animal类并实现了各自的make_sound()方法,分别模拟狗和猫发出的声音。
  • AnimalFactory类作为抽象工厂,定义了一个静态方法create_animal(),该方法接收动物类型和名字作为参数,根据传入的动物类型创建相应的具体动物对象。这里使用静态方法简化了示例,实际应用中也可以定义为普通方法并创建AnimalFactory的实例来调用。
  • 客户端代码中,创建了AnimalFactory实例,并通过调用其create_animal()方法创建了DogCat对象。客户端无需知道如何直接创建这些对象,只需与AnimalFactory交互并传递所需动物的类型和名称即可。

        这个例子展示了工厂方法模式在Python中的应用,通过工厂方法创建对象,客户端代码与具体的动物创建逻辑解耦,增加了系统的灵活性和可扩展性。如果需要添加新的动物类型(如兔子),只需定义新的动物类并更新工厂方法中的逻辑即可,无需改动客户端代码。

# 抽象产品
class Animal:def __init__(self, name):self.name = namedef make_sound(self):raise NotImplementedError("Subclasses must implement this abstract method")def __str__(self):return f"{self.name} makes {self.make_sound()} sound"# 具体产品
class Dog(Animal):def make_sound(self):return "Woof!"class Cat(Animal):def make_sound(self):return "Meow!"# 抽象工厂
class AnimalFactory:@staticmethoddef create_animal(animal_type, name):if animal_type == "dog":return Dog(name)elif animal_type == "cat":return Cat(name)else:raise ValueError(f"Unsupported animal type: {animal_type}")# 客户端代码
def main():animal_factory = AnimalFactory()dog = animal_factory.create_animal("dog", "Rex")print(dog)cat = animal_factory.create_animal("cat", "Whiskers")print(cat)if __name__ == "__main__":main()

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

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

相关文章

我与C++的爱恋:日期计算器

​ ​ 🔥个人主页:guoguoqiang. 🔥专栏:我与C的爱恋 朋友们大家好啊,在我们学习了默认成员函数后,我们通过上述内容,来实现一个简易的日期计算器。 ​ ​ 头文件的声明 #pragma once #incl…

面试经典-Redis数据库的数据倾斜

一、定义 对于集群系统,一般缓存是分布式的,即不同节点负责一定范围的缓存数据。我们把缓存数据分散度不够,导致大量的缓存数据集中到了一台或者几台服务节点上,称为数据倾斜。一般来说数据倾斜是由于负载均衡实施的效果不好引起…

K8S调度下的ingress-controller集群的实现以及nginx配置

# 22、K8S调度下的ingress-controller集群的实现以及nginx配置 目标: 1. 实现ingress-controller的集群部署 实现方法: 1. 为ingress-controller 规划两个节点 2.将这两个节点 打上自定义的 label 3.修改yaml文件,并重新创建 ingress-co…

签约棒球自由球员算法设计

签约棒球自由球员算法设计 1. 问题描述2. 算法设计2.1 动态规划2.2 状态转移方程2.3 初始化2.4 最终结果 3. 算法实现3.1 伪代码3.2 C代码示例 1. 问题描述 假设你是一支棒球大联盟球队的总经理。在赛季休季期间,你需要签入一些自由球员。球队老板给你的预算为 X美…

攻防世界fileclude题解

攻防世界fileclude题解 ​​ 题目要求file1和file2参数不能为空 且file2这个文件内容值为hello ctf,用php://input 然后POST体内输入hello ctf即可满足这个if条件 满足这个条件后就会包含file1变量所指定的那个文件。用php伪协议来跨目录包含一下flag.php文件就可以…

人工智能培训老师叶梓:如何通过Prompt优化提升GPT-4性能

在人工智能领域,尤其是自然语言处理(NLP)中,Prompt工程是一种通过精心设计的提示(prompt)来引导模型生成期望输出的技术。最近,微软的研究团队通过Prompt优化策略,在医疗领域取得了显…

Redis系列1:深刻理解高性能Redis的本质

1 背景 分布式系统绕不开的核心之一的就是数据缓存,有了缓存的支撑,系统的整体吞吐量会有很大的提升。通过使用缓存,我们把频繁查询的数据由磁盘调度到缓存中,保证数据的高效率读写。 当然,除了在内存内运行还远远不够…

K3S 证书有效期和续签问题

本文使用k3s版本:k3s version v1.24.17k3s1 (026bb0ec) 默认安装情况下,ca证书有效期是10年,普通证书有效期是1年。 普通证书 k3s官网描述:K3s 客户端和服务器证书自颁发日起 365 天内有效。每次启动 K3s 时,已过期或…

linux 云计算平台基本环境(知识准备篇)

为了更多的了解云计算平台,结合云计算和linux的知识写了一篇云计算的介绍和汇总。 文章目录 前言1. centos的软件管理1.1 yum软件包管理1.1.1 yum命令语法:1.1.2 安装软件包的步骤1.1.3 yum源 2. 主机名管理与域名解析3. centos的防火墙管理4. openstack…

java锁介绍

乐观锁 乐观地认为并发访问不会造成数据冲突,只在更新时检查是否有冲突。乐观锁和CAS的关系可以用“乐观锁是一种思想,CAS是一种具体的实现”来理解。 当使用CAS操作修改数据时,如果版本号不匹配或者其他线程已经修改了要操作的数据&#x…

面试题集中营—分布式共识算法

分布式共识算法目标 分布式主要就是为了解决单点故障。一开始只有一个服务节点提供服务,如下图所示。那么如果服务节点挂了,对不起等着吧。 为了服务的高可用性,我们一般都会多引入几个副节点当备份,当服务节点挂了,就…

记一次Mac(M1)交叉编译Windows系统的过程

做了一个导出文件项目来实践学习GO的成果,开发完成后,在本地调试环境一切正常,打包到Windows测试出现了报错Error: Binary was compiled with CGO_ENABLED0, go-sqlite3 requires cgo to work. This is a stub。后研究得知,gorm的…

如何逃过极域的管控

本文由Jzwalliser原创,发布在CSDN平台上,遵循CC 4.0 BY-SA协议。 因此,若需转载/引用本文,请注明作者并附原文链接,且禁止删除/修改本段文字。 违者必究,谢谢配合。 个人主页:blog.csdn.net/jzw…

【Java框架】Spring框架(四)——Spring中的Bean的创建与生命周期

目录 SpringBean的创建步骤后置处理器(PostProcessor)BeanFactoryPostProcessorBeanPostProcessorInstantiationAwareBeanPostProcessorpostProcessBeforeInstantiationpostProcessAfterInstantiationpostProcessProperties SmartInstantiationAwareBeanPostProcessordetermine…

医疗大模型产品设计

医疗领域的大型模型可以涵盖许多功能点,以提供全面的医疗支持和解决方案。以下是一些可能的功能点设计: 1. **疾病诊断与预测**:利用机器学习算法和医疗数据对患者的症状进行诊断和预测,帮助医生提供更准确的诊断和治疗建议。 2…

如何采集opc服务器数据上传云端

为了进一步提高生产效率,生产制造的不断朝着智能化发展和升级,传统的自动化生产系统已经不能满足需求。传统的SCADA系统一般是用于现场的数据采集与控制,但是本地控制已经无法满足整个工厂系统智能化数字化的需求,智能化数字化是需…

呼叫系统的技术实现原理和运作流程,ai智能系统,呼叫中心外呼软交换部署

呼叫系统的技术实现原理和运作流程可以涉及多个组成部分,包括硬件设备、软件系统和通信协议。以下是一般情况下呼叫系统的技术实现原理和运作流程的概述: 硬件设备: 服务器:用于承载呼叫系统的核心软件和数据库。电话交换机&#…

《手把手教你》系列基础篇(九十五)-java+ selenium自动化测试-框架之设计篇-java实现自定义日志输出(详解教程)

1.简介 前面宏哥一连几篇介绍如何通过开源jar包Log4j.jar、log4j2.jar和logback实现日志文件输出,Log4j和logback确实很强大,能生成三种日志文件,一种是保存到磁盘的日志文件,一种是控制台输出的日志,还有一种是HTML格…

Docker 镜像仓库常见命令

Docker Registry (镜像仓库) 常用命令 docker login 功能:登录到一个 Docker 镜像仓库,如果没有指定镜像仓库的地址,默认就是官方的 Docker Hub 仓库。 语法: docker login [options] [server]选项: -u:登…

字母加密(C语言)

一、题目; 为使电文保密,往往按一定规律将其转换成密码,收报人再按约定的规律将其译回原文。例如,可以按以下规律将电文变成密码:将字母A变成字母E,a变成e,即变成其后的第4个字母,W…