当前位置: 首页 > news >正文

设计模式:工厂方法模式(C#、JAVA、JavaScript、C++、Python、Go、PHP):

本节主要介绍设计模式中的工厂方法模式。

简介:

工厂方法模式,它是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
它定义了一个用于创建对象的工厂接口,让子类决定实例化哪个类。在工厂方法模式中,父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。这种模式将类实例化操作延迟到子类中完成,即由子类来决定究竟应该实例化哪个类。

工厂方法模式的创建步骤如下:
1、创建抽象工厂类,定义具体工厂的公共接口。
2、创建抽象产品类,定义具体产品的公共接口。
3、创建具体产品类,继承抽象产品类并定义具体产品的生产。
4、创建具体工厂类,继承抽象工厂类并定义创建对应具体产品实例的方法。
5、外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例。

工厂方法模式的优点,主要包括:
1、增加新的产品类时无需修改现有系统:当需要增加一个新的产品时,只需要创建一个新的具体工厂和具体产品类,符合“开放-封闭”原则,增加了系统的灵活性和可扩展性。
2、封装了产品对象的创建细节:客户端只需要使用具体工厂类创建产品对象,无需关心对象是如何被创建的,这样就可以将产品对象的创建细节封装在具体工厂类中。
3、系统具有良好的灵活性和可扩展性:通过使用工厂方法模式,可以在不改变现有客户端代码的情况下,增加或修改产品类和工厂类,具有较强的灵活性。

工厂方法模式的缺点,主要包括:
1、增加额外的编写工作量:在增加新产品时,需要编写新的具体产品类和对应的具体工厂类,增加了系统的复杂度,需要更多的类需要编译和运行,给系统带来一些额外的开销。
2、需要考虑系统的抽象性和理解难度:为了增加系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

​​​​​​​

示例

一、C#工厂方法模式

以下是一个示例,展示了如何在C#中实现工厂方法模式:

// 产品的抽象类  
public abstract class Product  
{  public abstract void Use();  
}  // 具体产品类1  
public class ConcreteProduct1 : Product  
{  public override void Use()  {  Console.WriteLine("使用具体产品1");  }  
}  // 具体产品类2  
public class ConcreteProduct2 : Product  
{  public override void Use()  {  Console.WriteLine("使用具体产品2");  }  
}  // 工厂的抽象类  
public abstract class Creator  
{  // 工厂方法,由子类实现具体的创建逻辑  public abstract Product CreateProduct();  
}  // 具体工厂类1  
public class ConcreteCreator1 : Creator  
{  public override Product CreateProduct()  {  return new ConcreteProduct1();  }  
}  // 具体工厂类2  
public class ConcreteCreator2 : Creator  
{  public override Product CreateProduct()  {  return new ConcreteProduct2();  }  
}  class Program  
{  static void Main(string[] args)  {  Creator creator1 = new ConcreteCreator1(); Product product1 = creator1.CreateProduct();   product1.Use();  Creator creator2 = new ConcreteCreator2  Product product2 = creator2.CreateProduct(); product2.Use();  }  
}

二、java工厂方法模式

以下是一个示例,展示了如何在Java中实现工厂方法模式:

// 抽象产品类  
public abstract class Product {  public abstract void use();  
}  // 具体产品类1  
public class ConcreteProduct1 extends Product {  @Override  public void use() {  System.out.println("使用具体产品1");  }  
}  // 具体产品类2  
public class ConcreteProduct2 extends Product {  @Override  public void use() {  System.out.println("使用具体产品2");  }  
}  // 抽象工厂类  
public abstract class Factory {  // 工厂方法,由子类实现具体的创建逻辑  public abstract Product createProduct();  
}  // 具体工厂类1  
public class ConcreteFactory1 extends Factory {  @Override  public Product createProduct() {  return new ConcreteProduct1();  }  
}  // 具体工厂类2  
public class ConcreteFactory2 extends Factory {  @Override  public Product createProduct() {  return new ConcreteProduct2();  }  
}  // Client代码  
public class Client {  public static void main(String[] args) {  Factory factory = new ConcreteFactory1(); // 可以根据实际需要更换为ConcreteFactory2  Product product = factory.createProduct();  product.use();  }  
}


三、javascript工厂方法模式

在JavaScript中,工厂方法模式通常可以通过构造函数和对象字面量的组合来实现。

// 抽象产品类  
class Product {  // 抽象方法  use() {  throw new Error('Use abstract method "use"');  }  
}  // 具体产品类1  
class ConcreteProduct1 extends Product {  use() {  console.log('使用具体产品1');  }  
}  // 具体产品类2  
class ConcreteProduct2 extends Product {  use() {  console.log('使用具体产品2');  }  
}  // 抽象工厂类  
class Factory {  // 工厂方法,由子类实现具体的创建逻辑  createProduct() {  throw new Error('Use abstract method "createProduct"');  }  
}  // 具体工厂类1  
class ConcreteFactory1 extends Factory {  createProduct() {  return new ConcreteProduct1();  }  
}  // 具体工厂类2  
class ConcreteFactory2 extends Factory {  createProduct() {  return new ConcreteProduct2();  }  
}  // Client代码  
class Client {  constructor(factory) {  this.factory = factory;  }  useProduct() {  let product = this.factory.createProduct();  product.use();  }  
}  // 使用Client类和ConcreteFactory1实例化一个新的Client对象并使用产品  
let client1 = new Client(new ConcreteFactory1());  
client1.useProduct();

四、C++工厂方法模式

以下是在C++中实现工厂方法模式:

//定义一个抽象产品类,它包含产品对象的公共接口。
class Product {  
public:  virtual void use() = 0; // 纯虚函数,具体实现由子类来决定  
};
//创建具体产品类,它们扩展了抽象产品类并实现了产品的具体行为。
class ConcreteProduct1 : public Product {  
public:  void use() override {  // 具体实现逻辑  std::cout << "使用具体产品1" << std::endl;  }  
};  class ConcreteProduct2 : public Product {  
public:  void use() override {  // 具体实现逻辑  std::cout << "使用具体产品2" << std::endl;  }  
};
//定义一个抽象工厂类,它包含一个工厂方法用于创建产品对象。这个方法是纯虚函数,具体实现由子类来决定。
class Factory {  
public:  virtual Product* createProduct() = 0; // 纯虚函数,具体实现由子类来决定  
};
//创建具体工厂类,它们扩展了抽象工厂类并实现了工厂方法的特定实现,以创建特定类型的产品对象。
class ConcreteFactory1 : public Factory {  
public:  Product* createProduct() override {  return new ConcreteProduct1();  }  
};  class ConcreteFactory2 : public Factory {  
public:  Product* createProduct() override {  return new ConcreteProduct2();  }  
};
//最后,在客户端代码中使用工厂方法模式来创建产品对象。客户端通过调用工厂对象的 createProduct 方法来创建产品对象,而不需要直接了解如何创建这些对象。这样可以提高客户端代码的灵活性和可维护性。
int main() {  Factory* factory = new ConcreteFactory1(); // 创建具体工厂对象  Product* product = factory->createProduct(); // 创建具体产品对象  product->use(); // 使用具体产品对象  delete factory; // 释放工厂对象内存  delete product; // 释放产品对象内存  return 0;  
}

五、python工厂方法模式

以下是在python中实现工厂方法模式:

from abc import ABCMeta, abstractmethod  # 抽象产品类  
class Product(metaclass=ABCMeta):  @abstractmethod  def operation(self):  pass  # 具体产品类1  
class ConcreteProduct1(Product):  def operation(self):  print("具体产品1被使用了")  # 具体产品类2  
class ConcreteProduct2(Product):  def operation(self):  print("具体产品2被使用了")  # 抽象工厂类  
class Factory(metaclass=ABCMeta):  @abstractmethod  def create_product(self):  pass  # 具体工厂类1  
class ConcreteFactory1(Factory):  def create_product(self):  return ConcreteProduct1()  # 具体工厂类2  
class ConcreteFactory2(Factory):  def create_product(self):  return ConcreteProduct2()  # Client代码  
if __name__ == "__main__":  factory1 = ConcreteFactory1()  product1 = factory1.create_product()  product1.operation()  factory2 = ConcreteFactory2()  product2 = factory2.create_product()  product2.operation()

    

六、go工厂方法模式

以下是一个示例,展示了如何在go中实现工厂方法模式:

//首先定义一个产品接口,该接口定义了产品的通用方法:
type Product interface {  Use()  
}
//然后,定义两个具体产品结构体,并实现Product接口的方法:
type ConcreteProduct1 struct{}  func (p *ConcreteProduct1) Use() {  fmt.Println("使用具体产品1")  
}  type ConcreteProduct2 struct{}  func (p *ConcreteProduct2) Use() {  fmt.Println("使用具体产品2")  
}
//接下来,定义一个工厂接口,该接口定义了一个创建产品的 方法:
type Factory interface {  CreateProduct() Product  
}
//然后,定义两个具体工厂结构体,并实现Factory接口的方法:
type ConcreteFactory1 struct{}  func (f *ConcreteFactory1) CreateProduct() Product {  return &ConcreteProduct1{}  
}  type ConcreteFactory2 struct{}  func (f *ConcreteFactory2) CreateProduct() Product {  return &ConcreteProduct2{}  
}
//最后,在客户端代码中,根据需要选择具体的工厂结构体实例化,然后使用该工厂结构体创建并使用产品:
func main() {  factory1 := &ConcreteFactory1{}  product1 := factory1.CreateProduct()  product1.Use()  factory2 := &ConcreteFactory2{}  product2 := factory2.CreateProduct()  product2.Use()  
}

七、PHP工厂方法模式

以下是一个示例,展示了如何在PHP中实现工厂方法模式:

//定义一个抽象产品接口(Abstract Product):
interface Product {  public function operation();  
}
//创建具体产品类实现抽象产品接口:
class ConcreteProduct1 implements Product {  public function operation() {  echo "具体产品1被使用了";  }  
}  class ConcreteProduct2 implements Product {  public function operation() {  echo "具体产品2被使用了";  }  
}
//定义一个抽象工厂类:
abstract class Creator {  abstract public function factoryMethod(): Product;  
}
//创建具体工厂类继承抽象工厂类:
class ConcreteCreator1 extends Creator {  public function factoryMethod() {  return new ConcreteProduct1();  }  
}  class ConcreteCreator2 extends Creator {  public function factoryMethod() {  return new ConcreteProduct2();  }  
}
//在客户端代码中,根据需要选择具体的工厂类实例化,并使用该工厂类创建并使用产品:
$creator1 = new ConcreteCreator1();  
$product1 = $creator1->factoryMethod();  
$product1->operation(); // 输出:具体产品1被使用了  $creator2 = new ConcreteCreator2();  
$product2 = $creator2->factoryMethod();  
$product2->operation(); // 输出:具体产品2被使用了

《完结》

相关文章:

设计模式:工厂方法模式(C#、JAVA、JavaScript、C++、Python、Go、PHP):

本节主要介绍设计模式中的工厂方法模式。 简介&#xff1a; 工厂方法模式&#xff0c;它是对简单工厂模式的进一步抽象化&#xff0c;其好处是可以使系统在不修改原来代码的情况下引进新的产品&#xff0c;即满足开闭原则。 它定义了一个用于创建对象的工厂接口&#xff0c;让…...

C++基础——指针

1 概述 指针的作用&#xff1a;可以通过指针间接访问内存 内存编号从0开始&#xff0c;一般使用十六进制数字表示&#xff0c;指针可以保存地址 2 指针变量定义和作用 int main() {//1、指针的定义int a 10; //定义整型变量a//指针定义语法&#xff1a; 数据类型 * 变量名 …...

PLC 学习day02 硬件输入/输入的知识

1.资料来源 1.链接&#xff1a;三菱PLC视频教程全集之FX3U基本单元输入接线_哔哩哔哩_bilibili 2. 链接&#xff1a; 三菱plc视频教程全集之FX3U基本单元输出接线_哔哩哔哩_bilibili 2. PLC 的输入部分器件连接。 2.1 PLC输入部分的硬件知识 1. 一般输入部分是PLC获取信息的地…...

rabbitMq (2)

RabbitMQ 消息应答与发布 文章目录 1. 消息应答1.2 自动应答1.2 手动应答1.3 代码案例 2. RabbitMQ 持久化2.1 队列持久化2.2 消息持久化 3. 不公平分发4. 预取值分发5. 发布确认5.1 发布确认逻辑5.2 开启发布确认的方法5.3 单个确认发布5.4 批量确认发布5.5 异步确认5.5.1 处理…...

通讯协议学习之路:RS422协议理论

通讯协议之路主要分为两部分&#xff0c;第一部分从理论上面讲解各类协议的通讯原理以及通讯格式&#xff0c;第二部分从具体运用上讲解各类通讯协议的具体应用方法。 后续文章会同时发表在个人博客(jason1016.club)、CSDN&#xff1b;视频会发布在bilibili(UID:399951374) 一、…...

剪映failed to initialize,cuda.is_available()为false解决

debug记录帖 错误1&#xff1a;打开剪映发现弹窗提示failed to initialize graphics backed for D3D11 错误2&#xff1a;torch版本、cuda版本&#xff08;之前的正常环境&#xff09;都对但是torch.cuda.is_available()为false 怀疑是显卡驱动的问题 打开Nvidia Geforce Exp…...

基于Spring Boot的LDAP开发全教程

写在前面 协议概述 LDAP&#xff08;轻量级目录访问协议&#xff0c;Lightweight Directory Access Protocol)是一种用于访问和维护分布式目录服务的开放标准协议,是一种基于TCP/IP协议的客户端-服务器协议&#xff0c;用于访问和管理分布式目录服务&#xff0c;如企业内部的…...

在 Linux 上保护 SSH 服务器连接的 8 种方法

SSH 是一种广泛使用的协议&#xff0c;用于安全地访问 Linux 服务器。大多数用户使用默认设置的 SSH 连接来连接到远程服务器。但是&#xff0c;不安全的默认配置也会带来各种安全风险。 具有开放 SSH 访问权限的服务器的 root 帐户可能存在风险。尤其是如果使用的是公共 IP 地…...

摩尔信使MThings的协议转换(数据网关)功能

摩尔信使MThings可以作为现场总线&#xff08;RS485&#xff09;和以太网的数据中枢&#xff0c;并拥有强大的Modbus协议转换功能。 数据网关功能提供协议转换和数据汇聚功能&#xff0c;可实现多维度映射&#xff0c;包括&#xff1a;不同的通道(总线)类型、协议类型&#xff…...

Mac安装Kali保姆级教程

Mac安装Kali保姆级教程 其他安装教程&#xff1a;使用VMware安装系统Window、Linux&#xff08;kali&#xff09;、Mac操作系统 1 虚拟机安装VM Fusion 去官网下载VM Fusion 地址&#xff1a;https://customerconnect.vmware.com/en/evalcenter?pfusion-player-personal-13 …...

利用Spring Boot框架做事件发布和监听

一、编写事件 1.编写事件类并集成spring boot 事件接口&#xff0c;提供访问事件参数属性 public class PeriodicityRuleChangeEvent extends ApplicationEvent {private final JwpDeployWorkOrderRuleDTO jwpDeployWorkOrderRuleDTO;public PeriodicityRuleChangeEvent(Obje…...

KingBase库模式表空间和客户端认证(kylin)

库、模式、表空间 数据库 数据库基集簇与数据库实例 KES集簇是由单个KES实例管理的数据库的集合KES集簇中的库使用相同的全局配置文件和监听端口、共享相关的进程和内存结构同一数据库集簇中的进程、相关的内存结构统称为实例 数据库 数据库是一个长期存储在计算机内的、有…...

h5的扫一扫功能 (非微信浏览器环境下)

必须在 https 域名下才生效 <template><div><van-field label"服务商编码" right-icon"scan" placeholder"扫描二维码获取" click-right-icon"getCameras" /> <div class"scan" :style"{disp…...

Typora 导出PDF 报错 failed to export as pdf. undefined 解决方案

情况 我想把一个很大的markdown 导出为 248页的pdf 然后就报错 failed to export as pdf. undefined 原因 &#xff1a; 个人感觉应该是图片太大了 格式问题之类导致的 解决 文件 -> 偏好设置 - > 导出 -> pdf -> 自定义 -> 把大小全部改为24mm (虽然图中是32 …...

[架构之路-239]:目标系统 - 纵向分层 - 中间件middleware

目录 前言&#xff1a; 一、中间件概述 1.1 中间件在软件层次中的位置 1.2 什么是中间件 1.3 为什么需要中间件 1.4 中间件应用场合&#xff08;应用程序不用的底层需求&#xff1a;计算、存储、通信&#xff09; 1.5 中间件分类 - 按内容分 二、嵌入式系统的中间件 2…...

javascript利用xhr对象实现http流的comet轮循,主要是利用readyState等于3的特点

//此文件 为前端获取http流 <!DOCTYPE html> <html xmlns"http://www.w3.org/1999/xhtml" lang"UTF-8"></html> <html><head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8"/&g…...

【Mybatis源码】XPathParser解析器

XPathParser是Mybatis中定义的进行解析XML文件的类,此类用于读取XML文件中的节点文本与属性;本篇我们主要介绍XPathParser解析XML的原理。 一、XPathParser构造方法 这里我们介绍主要的构造方法 public XPathParser(InputStream inputStream, boolean validation, Propert…...

辉视智慧酒店解决方案助力传统酒店通过智能升级焕发新生

辉视智慧酒店解决方案基于强大的物联网平台&#xff0c;将酒店客控、网络覆盖、客房智能化控制、酒店服务交互等完美融合&#xff0c;打造出全方位的酒店智慧化产品。利用最新的信息化技术&#xff0c;我们推动酒店智慧化转型&#xff0c;综合运用前沿的信息科学和技术、消费方…...

文件和命令的查找与处理

1.命令查找 which which 接命令 2.文件查找 find 按文件名字查找 准确查找 find / -name "hosts" 粗略查找 find / -name "ho*ts" 扩展名查找 find / -name "*.txt" 按文件类型查找 find / -type f 文件查找 find / -ty…...

第七章:最新版零基础学习 PYTHON 教程—Python 列表(第三节 -Python程序访问列表中的索引和值)

有多种方法可以访问列表的元素,但有时我们可能需要访问元素及其所在的索引。让我们看看访问列表中的索引和值的所有不同方法。 目录 使用Naive 方法访问列表中的索引和值 使用列表理解访问列表中的索引和值...

接口测试面试题整理​​​​​​​

HTTP, HTTPS协议 什么是DNSHTTP协议怎么抓取HTTPS协议说出请求接口中常见的返回状态码http协议请求方式HTTP和HTTPS协议区别HTTP和HTTPS实现机有什么不同POST和GET的区别HTTP请求报文与响应报文格式什么是Http协议无状态协议?怎么解决HTTP协议无状态协议常见的POST提交数据方…...

【保姆级教程】ChatGPT/GPT4科研技术应用与AI绘图

查看原文>>>https://mp.weixin.qq.com/s?__bizMzAxNzcxMzc5MQ&mid2247663763&idx1&snbaeb113ffe0e9ebf2b81602b7ccfa0c6&chksm9bed5f83ac9ad6955d78e4a696949ca02e1e531186464847ea9c25a95ba322f817c1fc7d4e86&token1656039588&langzh_CN#rd…...

凉鞋的 Godot 笔记 202. 变量概述与简介

202. 变量概述与简介 想要用好变量不是一件简单的事情&#xff0c;因为变量需要命名。 我们可以从两个角度去看待一个变量&#xff0c;第一个角度是变量的功能&#xff0c;第二个是变量的可读性。 变量的功能其实非常简单&#xff0c;变量可以存储一个值&#xff0c;这个值是…...

HTML 常用标签及练习

常用标签 <head>中的标签 概述 head中的内容不显示到页面上 标签说明<title>定义网页的标题<meta>定义网页的基本信息&#xff08;供搜索引擎&#xff09;<style>定义CSS样式<link>链接外部CSS文件或脚本文件<script>定义脚本语言<…...

Python 编程基础 | 第六章-包与模块管理 | 1、包与模块简介

一、模块 在程序开发过程中&#xff0c;文件代码越来越长&#xff0c;维护越来越不容易。可以把很多不同的功能编写成函数&#xff0c;放到不同的文件里&#xff0c;方便管理和调用。在Python中&#xff0c;一个.py文件就称之为一个模块&#xff08;Module&#xff09;。 1、简…...

为中小企业的网络推广策略解析:扩大品牌知名度和曝光度

目前网络推广已经成为企业获取潜在客户和提升品牌知名度的重要手段。对于中小企业而言&#xff0c;网络推广是一个具有巨大潜力和可行性的营销策略。在本文中&#xff0c;我们将探讨中小企业为什么有必要进行网络推广&#xff0c;并分享一些实用的网络推广策略。 一、扩大品牌知…...

资源受限MCU Flash空间占用优化

资源受限MCU Flash空间占用优化步骤&#xff1a; 避免重复功能&#xff0c;排查软件工程中&#xff0c;重复功能的代码片段&#xff0c;抽象出来&#xff0c;重新进行封装&#xff1b;减少内联函数inline&#xff0c;内联函数过大且过多的调用无疑会增加代码量&#xff0c;占用…...

冰蝎默认加密的流量解密

破解冰蝎的默认加密 流量包分析 上传的冰蝎流量包 POST /web-zh/DVWA/vulnerabilities/upload/ HTTP/1.1 Host: 192.168.197.111 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0 Accept: text/html,application/xhtmlxml,a…...

C#字符串操作:拼接、截取、分割等高效处理方法

目录 1.前言2. 字符串拼接 (String Concatenation)3. 字符串截取 (String Substring)4. 字符串分割 (String Split)5. 字符串替换 (String Replace)6. 字符串大小写转换 (String Case Conversion)7. 结论 1.前言 在C#编程中&#xff0c;字符串操作是不可避免的一部分。无论是拼…...

垃圾邮件(短信)分类算法实现 机器学习 深度学习 计算机竞赛

文章目录 0 前言2 垃圾短信/邮件 分类算法 原理2.1 常用的分类器 - 贝叶斯分类器 3 数据集介绍4 数据预处理5 特征提取6 训练分类器7 综合测试结果8 其他模型方法9 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 垃圾邮件(短信)分类算…...