设计模式:抽象工厂模式(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)
大家好!本节主要介绍设计模式中的抽象工厂模式。 简介: 抽象工厂模式,它是所有形态的工厂模式中最为抽象和最具一般性的一种形态。它用于处理当有多个抽象角色时的情况。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指…...
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…...

【网络安全】安全的系统配置
系统配置是网络安全的重要组成部分。一个不安全的系统配置可能会使网络暴露在攻击者面前,而一个安全的系统配置可以有效地防止攻击者的入侵。在本文中,我们将详细介绍如何配置一个安全的系统,包括操作系统配置,网络服务配置&#…...
conda使用一般步骤
Terminal: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配置…...

如何做好需求收集?方法和步骤
需求收集是理解你想要构建什么以及为什么要构建它的过程。需求收集通常被视为开发软件应用,或开发硬件产品的一部分。其重要性不言而喻。据调查显示50%以上产品在市场上失败的原因,是由于忽视了用户需求。 一、需求收集为什么会困难? 困扰项…...
SpringBoo整合WebSocket实战演练——Java入职十三天
前言 本文将介绍如何在Spring Boot应用程序中使用WebSocket实现服务端向客户端推送消息。Spring Boot和WebSocket的整合实现服务端向客户端推送消息,使得客户端能够实时接收并处理服务器发来的信息。WebSocket协议是一种双向通信的网络协议,使得客户端和服务器能够建立持久连…...

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

详解cv2.addWeighted函数【使用 OpenCV 添加(混合)两个图像-Python版本】
文章目录 简介函数原型代码示例参考资料 简介 有的时候我们需要将两张图片在alpha通道进行混合,比如深度学习数据集增强方式MixUp。OpenCV的addWeighted提供了相关操作,此篇博客将详细介绍这个函数,并给出代码示例。🚀Ƕ…...

单链表经典OJ题:反转链表
题目: 给你单链表的头节点 head ,i请你反转链表,并返回反转后的链表。 图例: 分析: 根据链表的特征,反转链表的本质便是改变节点内部的指针方向。 将原先指向下一个节点的指针进行修改,将其的…...
软考高级信息系统项目管理师系列论文六:论信息系统项目的人力资源管理
软考高级信息系统项目管理师系列论文六:论信息系统项目的人力资源管理 一、人力资源管理相关知识二、摘要三、正文四、总结一、人力资源管理相关知识 软考高级信息系统项目管理师系列之十七:项目人力资源管理二、摘要 2021年7 月,我参加了╳╳市物价局发起的“智慧物价”信息…...

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

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

SMAP(Soil Moisture Active and Passive)数据下载
SMAP(Soil Moisture Active and Passive)数据下载 打开网站先注册登录用户 然后打开SMAP下载的网站 点击HTTPS File System进入下载页面 然后点击HDF文件下载 下载之后在HDF View里面预览...
【Huawei S5700交换机】产品介绍
产品特点 S5700系列以太网交换机,是华为公司为满足大带宽接入和以太多业务汇聚而推出的新一代绿色节能的全千兆高性能以太交换机。它基于新一代高性能硬件和华为公司统一的VRP(Versatile Routing Platform)平台,具备大容量、高可…...

华为Atlas 200I DK A2开发者套件--基础使用配置
文章目录 前言一、快速开始二、通过路由器联网三、USB相机总结 前言 Atlas 200I DK A2基础使用配置方法。准备好键鼠、显示器、网线、USB拓展器。 一、快速开始 下载最新官方Windows版本昇腾开发者套件一键制卡工具: 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问题,状态转移方程: dp[i][j] min( dp[i][k] dp[k1][j] w[i][j] ) //w[i][j]是从i到j的,一个定值 不随k改变,而且w的值只和i j有关,是它们的二元函数。 其中i<k<j ,初始值dp[i][i]已知。 含义&#x…...

Jmeter(四):请求默认值元件应用,正则表达式提取器元件讲解
Jmeter请求默认值元件应用 HTTP请求默认值 在公司内部进行测试的时候,一般测试环境访问的接口地址(服务器名称 或IP)、端口、协议一般都是不变的,但http请求取样器每个请求都要求写一遍 这些信息,在实际HTTP请求取样…...
LCR 001. 两数相除
剑指Offer通关 力扣搜索LCR即为剑指Offer的所有题目。 LCR 001. 两数相除 快速乘 解析: 题目规定只能用32位整数,所以取值范围在-2^31 ~ 2^31 - 1 之间。这里的特殊情况为什么不考虑被除数和除数为最大值?因为后面会将所有的数都转为负数…...

LeCun和Bengio“吵”起来了,人工智能是“潘多拉魔盒”吗?
作者 | 谢年年 上周末,深度学习领域最有影响力的三巨头之二Yann LeCun和Yoshua Bengio就AI的潜在风险和安全问题引发了一场激烈辩论,人工智能是“潘多拉魔盒”吗?这场辩论引来众多AI知名人士围观。 LeCun在Facebook上发起了这场辩论ÿ…...
代码训练LeetCode(23)随机访问元素
代码训练(23)LeetCode之随机访问元素 Author: Once Day Date: 2025年6月5日 漫漫长路,才刚刚开始… 全系列文章可参考专栏: 十年代码训练_Once-Day的博客-CSDN博客 参考文章: 380. O(1) 时间插入、删除和获取随机元素 - 力扣(LeetCode)力…...
【JS进阶】ES6 实现继承的方式
ES6 实现继承的方式 基本语法 class Parent {constructor(name) {this.name name;this.colors [red, blue];}sayName() {console.log(this.name);} }class Child extends Parent {constructor(name, age) {super(name); // 必须调用super(),且在使用this之前thi…...
护网面试题目2025
护网基础试题 一、描述外网打点的流程? 靶标确认、信息收集、漏洞探测、漏洞利用、权限获取。最终的目的是获取靶标的系统权限/关键数据。在这个过程中,信息收集最为重要。掌握靶标情报越多,后续就会有更多的攻击方式去打点。比如ÿ…...

电脑提示dll文件缺失怎么办 dll修复方法
当你在使用某些应用程序或启动电脑时,看到提示“DLL文件缺失”的错误信息,这通常意味着某个必要的动态链接库(DLL)文件无法被找到或加载,导致软件无法正常运行。本文将详细介绍如何排查和修复DLL文件缺失的问题&#x…...
Perl One-liner 数据处理——基础语法篇【匠心】
Perl(Practical Extraction and Report Language)是一种功能强大且灵活的脚本语言,因其强大的文本处理能力和简洁的语法而广受开发者和系统管理员的喜爱。特别是在命令行环境下,Perl 的 one-liner(单行脚本)以其高效、简洁的特点,成为数据处理、文本转换和快速原型设计的…...
vue3+elementplus表格表头加图标及文字提示
表头加自定义内容有很多种方法,包括使用el-icon,插槽,CSS 伪元素添加图标还有font-awesome等等。 一、方法一:使用render-header属性 <el-table :data"tableData"><el-table-column prop"name" la…...

【物联网-S7Comm协议】
物联网-S7Comm协议 ■ 调试工具■ S7协议-简介■ S7协议和modbusTCP协议区别■ OSI 层 S7 协议■ S7协议数据结构 (TPKTCOTPS7Comm)■ TPKT(第五层:会话层) 总共占4个字节■ COTP(第六层:表示层…...

ubuntu24.04 使用apt指令只下载不安装软件
比如我想下载net-tools工具包及其依赖包可以如下指令 apt --download-only install net-tools 自动下载的软件包在/var/cache/apt/archives/目录下...
docker中组合这几个命令来排查 import 模块失败 的问题
pwd ls echo $PYTHONPATH这三个命令是你在 Linux 或 Docker 容器中常用来「查看环境状态」的基础命令。 ✅ 1. echo $PYTHONPATH 🔍 含义 这是在查看当前的 Python 模块搜索路径。 🧠 分解解释: echo:打印某个变量的值&#x…...

网络攻防技术十三:网络防火墙
文章目录 一、网络防火墙概述1、网络型防火墙(网络防火墙)2、Web应用防火墙3、数据库防火墙4、主机防火墙(个人防火墙)5、网络防火墙的功能 二、防火墙工作原理1、无状态包过滤防火墙2、有状态包过滤防火墙(状态检测/动…...