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

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

大家好!本节主要介绍设计模式中的抽象工厂模式。

简介:

抽象工厂模式,它是所有形态的工厂模式中最为抽象和最具一般性的一种形态。它用于处理当有多个抽象角色时的情况。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体情况下创建多个产品组中的产品对象。这种模式根据里氏替换原则,任何接受父类型的地方都应当能够接受子类型。实际上,系统所需要的仅仅是类型与这些抽象产品角色相同的一些实例。

抽象工厂模式的创建步骤如下:
1、创建抽象工厂类,定义具体工厂的公共接口。
2、创建抽象产品族类,定义抽象产品的公共接口。
3、创建抽象产品类(继承抽象产品族类),定义具体产品的公共接口。
4、创建具体产品类(继承抽象产品类)&定义生产的具体产品。
5、创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法。
6、客户端通过实例化具体的工厂类,并调用其创建不同目标产品的方法创建不同具体产品类的实例。

抽象工厂模式的优点,主要包括:
1、隔离了具体类的生产:使得客户并不需要知道什么被创建,降低了客户端与具体产品的耦合度。
2、保证同一产品族的使用:当一个产品族中的多个对象被设计成一起工作时,抽象工厂模式能保证客户端始终只使用同一个产品族中的对象。
3、易于扩展:增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
4、提供更高层次的抽象:抽象工厂模式能够提供更高层次的抽象,同时也能够更好地管理不同产品族之间的关系,从而使得系统更加灵活和易于扩展。
5、符合单一职责原则:每个具体工厂只负责创建一组具体产品,不会与其他产品产生耦合。

抽象工厂模式的缺点,主要包括:
1、增加新的产品等级结构麻烦:需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这可能会违背开闭原则。
2、抽象工厂模式需要识别和定义所有的抽象产品类和具体产品类,这会增加系统的复杂性。
3、在客户端代码中需要显式地指定使用哪个具体工厂,这会增加客户端代码的复杂性。
4、如果出现异常情况,很难确定是哪一个工厂或者是哪一个产品出现问题,因为它们都是独立的对象。
5、实现抽象工厂模式需要消耗较多的时间和精力,因为需要分离出抽象工厂类和具体工厂类,并且需要针对每个具体工厂类编写对应的客户端代码。


示例:

在实际应用中,工厂的创建和产品的生产可能会更加复杂,并且可能会有更多的具体工厂和产品类。


一、C#抽象工厂模式

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

//首先,定义一个接口来表示工厂:
public interface IFactory {  Product CreateProduct();  
}
//接下来,实现具体工厂类,它们分别创建具体产品对象:
public class ConcreteFactoryA : IFactory {  public Product CreateProduct() {  return new ConcreteProductA();  }  
}  public class ConcreteFactoryB : IFactory {  public Product CreateProduct() {  return new ConcreteProductB();  }  
}
//然后,定义一个抽象产品接口和具体产品类来实现该接口:
public interface Product {  void Use();  
}  public class ConcreteProductA : Product {  public void Use() {  Console.WriteLine("Using Product A");  }  
}  public class ConcreteProductB : Product {  public void Use() {  Console.WriteLine("Using Product B");  }  
}
//最后,编写客户端代码来使用抽象工厂模式创建产品对象:
public class Client {  public void UseProduct(IFactory factory) {  Product product = factory.CreateProduct();  product.Use();  }  
}
//在主程序中,可以创建客户端对象并使用不同的工厂对象来创建产品对象:
static void Main() {  Client client = new Client();  IFactory factoryA = new ConcreteFactoryA();  client.UseProduct(factoryA); // Output: Using Product A  IFactory factoryB = new ConcreteFactoryB();  client.UseProduct(factoryB); // Output: Using Product B  
}


二、java抽象工厂模式模式

抽象工厂模式通常通过以下方式实现:

//抽象工厂接口:这是一个工厂的抽象接口,它定义了创建对象的方法,但并不实现。
public interface AbstractFactory {  ProductA createProductA();  ProductB createProductB();  
} //具体工厂类:这些类实现了抽象工厂接口,并知道如何创建特定类型的对象。
public class ConcreteFactory1 implements AbstractFactory {  @Override  public ProductA createProductA() {  return new ProductA1();  }  @Override  public ProductB createProductB() {  return new ProductB1();  }  
}  public class ConcreteFactory2 implements AbstractFactory {  @Override  public ProductA createProductA() {  return new ProductA2();  }  @Override  public ProductB createProductB() {  return new ProductB2();  }  
}//抽象产品接口:这些接口定义了产品的规范,即产品应具有的通用方法。
public interface ProductA {  void use();  
}  public interface ProductB {  void use();  
}//具体产品类:这些类实现了抽象产品接口,并提供了具体的实现。
public class ProductA1 implements ProductA {  @Override  public void use() {  System.out.println("Using product A1");  }  
}  public class ProductA2 implements ProductA {  @Override  public void use() {  System.out.println("Using product A2");  }  
}  //最后,在客户端代码中,我们通常会使用一个“提供者”类(如名称“Provider”)来获取工厂对象,然后使用这些工厂对象来创建产品。这样可以让客户端代码与工厂的具体实现解耦。
public class Client {  private AbstractFactory factory;  public Client(AbstractFactory factory) {  this.factory = factory;  }  public void useProducts() {  ProductA productA = factory.createProductA();  productA.use();  ProductB productB = factory.createProductB();  productB.use();  }  
}
//主程序    
public static void main(String[] args) {  Client client = new Client();  AbstractFactory factory1 = new ConcreteFactory1();  client.UseProduct(factory1); // Output: Using Product A  AbstractFactory factory2 = new ConcreteFactory2();  client.UseProduct(factory2); // Output: Using Product B  
}


三、javascript抽象工厂模式

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

// 抽象工厂接口  
function AbstractFactory() {  this.createProduct = function() {  throw new Error("This method is abstract and has to be implemented");  };  
}  // 具体工厂类1  
function ConcreteFactory1() {}  
ConcreteFactory1.prototype.createProduct = function() {  return new Product1();  
};  // 具体工厂类2  
function ConcreteFactory2() {}  
ConcreteFactory2.prototype.createProduct = function() {  return new Product2();  
};  // 产品接口  
function Product() {}  
Product.prototype.use = function() {  throw new Error("This is an abstract method and has to be implemented");  
};  // 产品类1  
function Product1() {}  
Product1.prototype = Object.create(Product.prototype);  
Product1.prototype.constructor = Product1;  
Product1.prototype.use = function() {  console.log("Using product 1");  
};  // 产品类2  
function Product2() {}  
Product2.prototype = Object.create(Product.prototype);  
Product2.prototype.constructor = Product2;  
Product2.prototype.use = function() {  console.log("Using product 2");  
};  // 客户端代码  
function Client() {  var factory;  this.setFactory = function(f) {  factory = f;  };  this.useFactory = function() {  var product = factory.createProduct();  product.use();  };  
}  var client = new Client();  
client.setFactory(new ConcreteFactory1());  
client.useFactory(); // Outputs: Using product 1  
client.setFactory(new ConcreteFactory2());  
client.useFactory(); // Outputs: Using product 2

四、C++抽象工厂模式

以下是在C++中实现抽象工厂模式:

#include <iostream>  
#include <string>  // 抽象产品接口  
class Product {  
public:  virtual void use() = 0;  
};  // 具体产品类1  
class ProductA : public Product {  
public:  void use() {  std::cout << "Using Product A" << std::endl;  }  
};  // 具体产品类2  
class ProductB : public Product {  
public:  void use() {  std::cout << "Using Product B" << std::endl;  }  
};  // 抽象工厂接口  
class Factory {  
public:  virtual Product* createProduct() = 0;  
};  // 具体工厂类1  
class FactoryA : public Factory {  
public:  Product* createProduct() {  return new ProductA();  }  
};  // 具体工厂类2  
class FactoryB : public Factory {  
public:  Product* createProduct() {  return new ProductB();  }  
};  int main() {  // 创建抽象工厂对象  Factory* factory = nullptr;  // 创建具体工厂类1的对象,并赋值给抽象工厂对象  FactoryA factoryA;  factory = &factoryA;  // 使用抽象工厂对象创建产品对象,并使用产品对象  Product* product = factory->createProduct();  product->use();  // 创建具体工厂类2的对象,并赋值给抽象工厂对象  FactoryB factoryB;  factory = &factoryB;  // 使用抽象工厂对象创建产品对象,并使用产品对象  product = factory->createProduct();  product->use();  return 0;  
}


五、python抽象工厂模式

以下是在python中实现抽象工厂模式:

#定义抽象产品接口,抽象产品接口定义了产品对象的通用方法。
class Product:  def use(self):  raise NotImplementedError("This method is abstract and has to be implemented")#实现具体产品类
class ProductA(Product):  def use(self):  print("Using Product A")  class ProductB(Product):  def use(self):  print("Using Product B")#定义抽象工厂接口,抽象工厂接口定义了创建产品对象的通用方法。
class Factory:  def createProduct(self):  raise NotImplementedError("This method is abstract and has to be implemented")#实现具体工厂类,具体工厂类继承抽象工厂接口并实现createProduct方法
class FactoryA(Factory):  def createProduct(self):  return ProductA()  class FactoryB(Factory):  def createProduct(self):  return ProductB()#创建客户端代码,客户端代码使用抽象工厂接口创建产品对象并使用它们。
factory = Factory()  # 创建抽象工厂对象  
product = factory.createProduct()  # 使用抽象工厂对象创建产品对象  
product.use()  # 使用产品对象


六、go抽象工厂模式

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

//定义接口:首先,定义出需要创建对象的接口,这个接口规定了对象的共有方法。
type Product interface {  Use()  
}  type ConcreteProductA struct{}  func (p *ConcreteProductA) Use() {  fmt.Println("Using Product A")  
}  type ConcreteProductB struct{}  func (p *ConcreteProductB) Use() {  fmt.Println("Using Product B")  
}//定义抽象工厂接口:接下来,定义出抽象工厂接口,这个接口规定了创建对象的方法。
type Factory interface {  CreateProduct() Product  
}  type ConcreteFactoryA struct{}  func (f *ConcreteFactoryA) CreateProduct() Product {  return &ConcreteProductA{}  
}  type ConcreteFactoryB struct{}  func (f *ConcreteFactoryB) CreateProduct() Product {  return &ConcreteProductB{}  
}//实现客户端代码:现在可以写客户端代码了,这个代码使用抽象工厂接口来创建产品对象。
func main() {  factoryA := &ConcreteFactoryA{}  productA := factoryA.CreateProduct()  productA.Use() // Output: Using Product A  factoryB := &ConcreteFactoryB{}  productB := factoryB.CreateProduct()  productB.Use() // Output: Using Product B  
}


七、PHP抽象工厂模式

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

// 抽象产品接口  
interface Product {  public function operation();  
}  // 具体产品类实现抽象接口  
class ConcreteProductA implements Product {  public function operation() {  echo "Product A operation\n";  }  
}  class ConcreteProductB implements Product {  public function operation() {  echo "Product B operation\n";  }  
}  // 抽象工厂接口  
interface Factory {  public function createProduct();  
}  // 具体工厂类实现抽象工厂接口,创建具体产品对象  
class ConcreteFactoryA implements Factory {  public function createProduct() {  return new ConcreteProductA();  }  
}  class ConcreteFactoryB implements Factory {  public function createProduct() {  return new ConcreteProductB();  }  
}  // 客户端代码使用抽象工厂对象创建具体产品对象  
class Client {  public function useProduct(Factory $factory) {  $product = $factory->createProduct();  $product->operation();  }  
}  // 示例用法  
$client = new Client();  
$factoryA = new ConcreteFactoryA();  
$client->useProduct($factoryA); // Output: Product A operation  $factoryB = new ConcreteFactoryB();  
$client->useProduct($factoryB); // Output: Product B operation

《完结》

相关文章:

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

大家好&#xff01;本节主要介绍设计模式中的抽象工厂模式。 简介&#xff1a; 抽象工厂模式&#xff0c;它是所有形态的工厂模式中最为抽象和最具一般性的一种形态。它用于处理当有多个抽象角色时的情况。抽象工厂模式可以向客户端提供一个接口&#xff0c;使客户端在不必指…...

ocpp-远程启动(RemoteStartTransaction)、远程停止(RemoteStopTransaction)

目录 1、介绍 2、远程启动-RemoteStartTransaction 3、远程停止-RemoteStopTransaction 4、代码 4.1 OcppRechongFeign 4.2 CmdController 4.3 CmdService 4.4 RemoteStartTransactionReq 4.5 接收报文-DataAnalysisController 4.6 接收报文实现类-DataAnalysisServi…...

【网络安全】安全的系统配置

系统配置是网络安全的重要组成部分。一个不安全的系统配置可能会使网络暴露在攻击者面前&#xff0c;而一个安全的系统配置可以有效地防止攻击者的入侵。在本文中&#xff0c;我们将详细介绍如何配置一个安全的系统&#xff0c;包括操作系统配置&#xff0c;网络服务配置&#…...

conda使用一般步骤

Terminal&#xff1a;conda create --name myenv python3.7 如果环境不行的话 1.source /opt/anaconda3/bin/activate 2.可能是没有源 vim ~/.condarc将需要的源装上 conda clean -i将原先的源删除 3.然后再conda create即可 4.需要激活环境 conda activate numpy 5.pycharm配置…...

如何做好需求收集?方法和步骤

需求收集是理解你想要构建什么以及为什么要构建它的过程。需求收集通常被视为开发软件应用&#xff0c;或开发硬件产品的一部分。其重要性不言而喻。据调查显示50%以上产品在市场上失败的原因&#xff0c;是由于忽视了用户需求。 一、需求收集为什么会困难&#xff1f; 困扰项…...

SpringBoo整合WebSocket实战演练——Java入职十三天

前言 本文将介绍如何在Spring Boot应用程序中使用WebSocket实现服务端向客户端推送消息。Spring Boot和WebSocket的整合实现服务端向客户端推送消息,使得客户端能够实时接收并处理服务器发来的信息。WebSocket协议是一种双向通信的网络协议,使得客户端和服务器能够建立持久连…...

众佰诚:抖音小店的体验分什么时候更新

随着移动互联网的发展&#xff0c;越来越多的电商平台开始涌现&#xff0c;其中抖音小店作为一种新型的电商模式&#xff0c;受到了许多用户的欢迎。然而&#xff0c;对于抖音小店的体验分更新时间&#xff0c;很多用户并不是很清楚。本文将对此进行详细的解答。 首先&#xff…...

详解cv2.addWeighted函数【使用 OpenCV 添加(混合)两个图像-Python版本】

文章目录 简介函数原型代码示例参考资料 简介 有的时候我们需要将两张图片在alpha通道进行混合&#xff0c;比如深度学习数据集增强方式MixUp。OpenCV的addWeighted提供了相关操作&#xff0c;此篇博客将详细介绍这个函数&#xff0c;并给出代码示例。&#x1f680;&#x1f6…...

单链表经典OJ题:反转链表

题目&#xff1a; 给你单链表的头节点 head &#xff0c;i请你反转链表&#xff0c;并返回反转后的链表。 图例&#xff1a; 分析&#xff1a; 根据链表的特征&#xff0c;反转链表的本质便是改变节点内部的指针方向。 将原先指向下一个节点的指针进行修改&#xff0c;将其的…...

软考高级信息系统项目管理师系列论文六:论信息系统项目的人力资源管理

软考高级信息系统项目管理师系列论文六:论信息系统项目的人力资源管理 一、人力资源管理相关知识二、摘要三、正文四、总结一、人力资源管理相关知识 软考高级信息系统项目管理师系列之十七:项目人力资源管理二、摘要 2021年7 月,我参加了╳╳市物价局发起的“智慧物价”信息…...

Kubeadm部署k8s集群

目录 主机准备 主机配置 修改主机名&#xff08;三个节点分别执行&#xff09; 配置hosts&#xff08;所有节点&#xff09; 关闭防火墙、selinux、swap、dnsmasq(所有节点) 安装依赖包&#xff08;所有节点&#xff09; 系统参数设置(所有节点) 时间同步(所有节点) 配…...

YOLOv7改进:新机制,扩展DCNv3,基于DCNv2优化 | CVPR2023 InternImage

💡💡💡本文属于原创独家改进:DCNv3优势:1) 共享投射权重;2) 引入多组机制;3)采样点调制标量归一化; DCNv3 | 亲测在多个数据集实现暴力涨点; 收录: YOLOv7高阶自研专栏介绍: http://t.csdnimg.cn/tYI0c ✨✨✨前沿最新计算机顶会复现 🚀🚀🚀YOL…...

SMAP(Soil Moisture Active and Passive)数据下载

SMAP&#xff08;Soil Moisture Active and Passive&#xff09;数据下载 打开网站先注册登录用户 然后打开SMAP下载的网站 点击HTTPS File System进入下载页面 然后点击HDF文件下载 下载之后在HDF View里面预览...

【Huawei S5700交换机】产品介绍

产品特点 S5700系列以太网交换机&#xff0c;是华为公司为满足大带宽接入和以太多业务汇聚而推出的新一代绿色节能的全千兆高性能以太交换机。它基于新一代高性能硬件和华为公司统一的VRP&#xff08;Versatile Routing Platform&#xff09;平台&#xff0c;具备大容量、高可…...

华为Atlas 200I DK A2开发者套件--基础使用配置

文章目录 前言一、快速开始二、通过路由器联网三、USB相机总结 前言 Atlas 200I DK A2基础使用配置方法。准备好键鼠、显示器、网线、USB拓展器。 一、快速开始 下载最新官方Windows版本昇腾开发者套件一键制卡工具&#xff1a; https://ascend-repo.obs.cn-east-2.myhuaweic…...

C++DAY47

头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPushButton> #include <QLabel> #include <QLineEdit> #include <QDebug>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public…...

四边形不等式

区间dp问题&#xff0c;状态转移方程&#xff1a; dp[i][j] min( dp[i][k] dp[k1][j] w[i][j] ) //w[i][j]是从i到j的&#xff0c;一个定值 不随k改变&#xff0c;而且w的值只和i j有关&#xff0c;是它们的二元函数。 其中i<k<j ,初始值dp[i][i]已知。 含义&#x…...

Jmeter(四):请求默认值元件应用,正则表达式提取器元件讲解

Jmeter请求默认值元件应用 HTTP请求默认值 在公司内部进行测试的时候&#xff0c;一般测试环境访问的接口地址&#xff08;服务器名称 或IP&#xff09;、端口、协议一般都是不变的&#xff0c;但http请求取样器每个请求都要求写一遍 这些信息&#xff0c;在实际HTTP请求取样…...

LCR 001. 两数相除

剑指Offer通关 力扣搜索LCR即为剑指Offer的所有题目。 LCR 001. 两数相除 快速乘 解析&#xff1a; 题目规定只能用32位整数&#xff0c;所以取值范围在-2^31 ~ 2^31 - 1 之间。这里的特殊情况为什么不考虑被除数和除数为最大值&#xff1f;因为后面会将所有的数都转为负数…...

LeCun和Bengio“吵”起来了,人工智能是“潘多拉魔盒”吗?

作者 | 谢年年 上周末&#xff0c;深度学习领域最有影响力的三巨头之二Yann LeCun和Yoshua Bengio就AI的潜在风险和安全问题引发了一场激烈辩论&#xff0c;人工智能是“潘多拉魔盒”吗&#xff1f;这场辩论引来众多AI知名人士围观。 LeCun在Facebook上发起了这场辩论&#xff…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...