设计模式:抽象工厂模式(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上发起了这场辩论ÿ…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...
