Go和Java实现抽象工厂模式
Go和Java实现抽象工厂模式
本文通过简单数据库操作案例来说明抽象工厂模式的使用,使用Go语言和Java语言实现。
1、抽象工厂模式
抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创
建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工
厂模式提供对象。
-
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
-
主要解决:主要解决接口选择的问题。
-
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
-
如何解决:在一个产品族里面,定义多个产品。
-
关键代码:在一个工厂里聚合多个同类产品。
-
应用实例:工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产
品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、
时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,但有利于说明抽象工
厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每
次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是
衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产
品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。
-
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
-
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里
面加代码。
-
使用场景:1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
-
注意事项:产品族难扩展,产品等级易扩展。
-
适用性:
一个系统要独立于它的产品的创建、组合和表示时。
一个系统要由多个产品系列中的一个来配置时。
当你要强调一系列相关的产品对象的设计以便进行联合使用时。
当你提供一个产品类库,而只想显示它们是接口而不是实现时。
2、Go实现简单数据库操作
我们通过 sqlserver 和 access 两种数据库对用户表和部门表进行操作。
package factory// 操作的用户表
type User struct {Id intName string
}
package factory// 用户表的操作
type IUser interface {InsertUser(User) boolGetUser(int)
}
package factoryimport "fmt"// SqlServer数据库操作用户表
type SqlServerUser struct {
}func (sqlServerUser *SqlServerUser) InsertUser(user User) bool {fmt.Println("SqlServer数据库插入用户!")return true
}func (sqlServerUser *SqlServerUser) GetUser(int) {fmt.Println("SqlServer数据库查询用户!")
}
package factoryimport "fmt"// Access数据库操作用户表
type AccessUser struct {
}func (accessUser *AccessUser) InsertUser(user User) bool {fmt.Println("Access数据库插入用户!")return true
}func (accessUser *AccessUser) GetUser(int) {fmt.Println("Access数据库查询用户!")
}
package factory// 操作的部门表
type Deployment struct {Id intName string
}
package factory// 部门表的操作
type IDeployment interface {InsertDeployment(Deployment) boolGetDeployment(int)
}
package factoryimport "fmt"// SqlServer数据库操作部门表
type SqlServerDeployment struct {
}func (sqlServerDeployment *SqlServerDeployment) InsertDeployment(deployment Deployment) bool {fmt.Println("SqlServer数据库插入部门!")return true
}func (sqlServerDeployment *SqlServerDeployment) GetDeployment(int) {fmt.Println("SqlServer数据库查询部门!")
}
package factoryimport "fmt"// Access数据库操作部门表
type AccessDeployment struct {
}func (accessDeployment *AccessDeployment) InsertDeployment(deployment Deployment) bool {fmt.Println("Access数据库插入部门!")return true
}func (accessDeployment *AccessDeployment) GetDeployment(int) {fmt.Println("Access数据库查询部门!")
}
package factory// 创建用户和部门操作的接口
type IFactory interface {CreateUser() IUserCreateDeployment() IDeployment
}
package factory// Access数据库工厂
type AccessFactory struct {
}func (accessFactory *AccessFactory) CreateUser() IUser {return &AccessUser{}
}func (accessFactory *AccessFactory) CreateDeployment() IDeployment {return &AccessDeployment{}
}
package factory// SqlServer数据库工厂
type SqlServerFactory struct {
}func (sqlServerFactory *SqlServerFactory) CreateUser() IUser {return &SqlServerUser{}
}func (sqlServerFactory *SqlServerFactory) CreateDeployment() IDeployment {return &SqlServerDeployment{}
}
package constantconst (SqlServer = "sqlserver"Access = "access"
)
package factoryimport "proj/constant"// 用一个简单工厂封装抽象工厂
type FactoryCreate struct {
}func (factoryCreate *FactoryCreate) NewFactory(dbType string) IFactory {switch dbType {case constant.SqlServer:return &SqlServerFactory{}case constant.Access:return &AccessFactory{}}return nil
}
package mainimport ("fmt""proj/constant". "proj/factory"
)// 测试
func main() {// 全局变量var factory IFactoryvar iUser IUservar iDeployment IDeployment// 操作用户user := User{}deployment := Deployment{}// SqlServer操作factory = &SqlServerFactory{}iUser = factory.CreateUser()iUser.InsertUser(user)iUser.GetUser(1)iDeployment = factory.CreateDeployment()iDeployment.InsertDeployment(deployment)iDeployment.GetDeployment(1)// Access操作factory = &AccessFactory{}iUser = factory.CreateUser()iUser.InsertUser(user)iUser.GetUser(1)iDeployment = factory.CreateDeployment()iDeployment.InsertDeployment(deployment)iDeployment.GetDeployment(1)fmt.Println("========================")// 简单工厂封装工厂方法factoryCreate := FactoryCreate{}// ==========SqlServer的工厂==========factory = factoryCreate.NewFactory(constant.SqlServer)iUser = factory.CreateUser()iUser.InsertUser(user)iUser.GetUser(1)iDeployment = factory.CreateDeployment()iDeployment.InsertDeployment(deployment)iDeployment.GetDeployment(1)// ==========Access的工厂==========factory = factoryCreate.NewFactory(constant.Access)iUser = factory.CreateUser()iUser.InsertUser(user)iUser.GetUser(1)iDeployment = factory.CreateDeployment()iDeployment.InsertDeployment(deployment)iDeployment.GetDeployment(1)
}
# 程序输出
SqlServer数据库插入用户!
SqlServer数据库查询用户!
SqlServer数据库插入部门!
SqlServer数据库查询部门!
Access数据库插入用户!
Access数据库查询用户!
Access数据库插入部门!
Access数据库查询部门!
========================
SqlServer数据库插入用户!
SqlServer数据库查询用户!
SqlServer数据库插入部门!
SqlServer数据库查询部门!
Access数据库插入用户!
Access数据库查询用户!
Access数据库插入部门!
Access数据库查询部门!
3、Java实现简单数据库操作
package com.factory;// 操作的用户表
public class User {private int Id;private String Name;public int getId() {return Id;}public void setId(int id) {Id = id;}public String getName() {return Name;}public void setName(String name) {Name = name;}
}
package com.factory;// 用户表的操作
public interface IUser {boolean InsertUser(User user);void GetUser(int id);
}
package com.factory;// SqlServer数据库操作用户表
public class SqlServerUser implements IUser {@Overridepublic boolean InsertUser(User user) {System.out.println("SqlServer数据库插入用户!");return true;}@Overridepublic void GetUser(int id) {System.out.println("SqlServer数据库查询用户!");}
}
package com.factory;// Access数据库操作用户表
public class AccessUser implements IUser {@Overridepublic boolean InsertUser(User user) {System.out.println("Access数据库插入用户!");return true;}@Overridepublic void GetUser(int id) {System.out.println("Access数据库查询用户!");}
}
package com.factory;// 操作的部门表
public class Deployment {private int Id;private String Name;public int getId() {return Id;}public void setId(int id) {Id = id;}public String getName() {return Name;}public void setName(String name) {Name = name;}
}
package com.factory;// 部门表的操作
public interface IDeployment {boolean InsertDeployment(Deployment deployment);void GetDeployment(int id);
}
package com.factory;// Access数据库操作部门表
public class AccessDeployment implements IDeployment {@Overridepublic boolean InsertDeployment(Deployment deployment) {System.out.println("Access数据库插入部门!");return true;}@Overridepublic void GetDeployment(int id) {System.out.println("Access数据库查询部门!");}
}
package com.factory;// SqlServer数据库操作部门表
public class SqlServerDeployment implements IDeployment {@Overridepublic boolean InsertDeployment(Deployment deployment) {System.out.println("SqlServer数据库插入部门!");return true;}@Overridepublic void GetDeployment(int id) {System.out.println("SqlServer数据库查询部门!");}
}
package com.factory;// 创建用户和部门操作的接口
public interface IFactory {IUser CreateUser();IDeployment CreateDeployment();
}
package com.factory;// Access数据库工厂
public class AccessFactory implements IFactory {@Overridepublic IUser CreateUser() {return new AccessUser();}@Overridepublic IDeployment CreateDeployment() {return new AccessDeployment();}
}
package com.factory;// SqlServer数据库工厂
public class SqlServerFactory implements IFactory {@Overridepublic IUser CreateUser() {return new SqlServerUser();}@Overridepublic IDeployment CreateDeployment() {return new SqlServerDeployment();}
}
package com.factory;// 用一个简单工厂封装抽象工厂
public class FactoryCreate {public IFactory NewFactory(DbType dbType) {switch (dbType) {case SQLSERVER:return new SqlServerFactory();case ACCESS:return new AccessFactory();}return null;}
}
package com.factory;public class Test {public static void main(String[] args) {// 全局变量IFactory factory = null;IUser iUser = null;IDeployment iDeployment = null;// 操作用户User user = new User();Deployment deployment = new Deployment();// SqlServer操作factory = new SqlServerFactory();iUser = factory.CreateUser();iUser.InsertUser(user);iUser.GetUser(1);iDeployment = factory.CreateDeployment();iDeployment.InsertDeployment(deployment);iDeployment.GetDeployment(1);// Access操作factory = new AccessFactory();iUser = factory.CreateUser();iUser.InsertUser(user);iUser.GetUser(1);iDeployment = factory.CreateDeployment();iDeployment.InsertDeployment(deployment);iDeployment.GetDeployment(1);System.out.println("========================");// 简单工厂封装工厂方法FactoryCreate factoryCreate = new FactoryCreate();// ==========SqlServer的工厂==========factory = factoryCreate.NewFactory(DbType.SQLSERVER);iUser = factory.CreateUser();iUser.InsertUser(user);iUser.GetUser(1);iDeployment = factory.CreateDeployment();iDeployment.InsertDeployment(deployment);iDeployment.GetDeployment(1);// ==========Access的工厂==========factory = factoryCreate.NewFactory(DbType.ACCESS);iUser = factory.CreateUser();iUser.InsertUser(user);iUser.GetUser(1);iDeployment = factory.CreateDeployment();iDeployment.InsertDeployment(deployment);iDeployment.GetDeployment(1);}}
# 程序输出
SqlServer数据库插入用户!
SqlServer数据库查询用户!
SqlServer数据库插入部门!
SqlServer数据库查询部门!
Access数据库插入用户!
Access数据库查询用户!
Access数据库插入部门!
Access数据库查询部门!
========================
SqlServer数据库插入用户!
SqlServer数据库查询用户!
SqlServer数据库插入部门!
SqlServer数据库查询部门!
Access数据库插入用户!
Access数据库查询用户!
Access数据库插入部门!
Access数据库查询部门!
4、简单工厂和工厂方法和抽象工厂类的区别
一句话概括工厂模式:
-
简单工厂:一个工厂类,一个产品抽象类。
-
工厂方法:多个工厂类,一个产品抽象类。
-
抽象工厂:多个工厂类,多个产品抽象类。
生活中的工厂模式:
-
简单工厂类:一个麦当劳店,可以生产多种汉堡。
-
工厂方法类:一个麦当劳店,可以生产多种汉堡。一个肯德基店,也可以生产多种汉堡。
-
抽象工厂类:百胜餐饮集团下有肯德基和百事公司,肯德基生产汉堡,百事公司生成百事可乐。
区别:
-
简单工厂:只有唯一工厂(简单工厂),一个产品接口/抽象类,根据简单工厂中的静态方法来创建具体产品对
象,适用于产品较少,几乎不扩展的情景。简单工厂中的方法集中了所有产品创建的逻辑,一旦要拓展新产品
时,就不得不修改工厂类,并且会造成工厂的逻辑过于复杂,开发中很少使用。
-
工厂方法:有多个工厂(抽象工厂+多个具体工厂),一个产品接口/抽象类,根据继承抽象工厂中的方法来多态
创建具体产品对象,适用于一个类型的多个产品。工厂方法模式中,在新增一个新产品时,就要新增一个具体
工厂和一个具体产品类,这样程序的拓展性就有了提高,符合了开闭原则,避免了简单工厂模式的缺点,但是
新增产品时需要新增两个类,会增加代码量,可谓是有舍有得,具体如何要结合具体情况来使用,开发中经常
使用。
-
抽象方法:有多个工厂(抽象工厂+多个具体工厂),多个产品接口/抽象类,对产品子类进行分组,根据继承
抽象工厂中的方法多态创建同组的不同具体产品对象,适用于多个类型的多个产品。抽象工厂模式是所有工厂
模式的一般形式,当抽象工厂模式退化到只有一个产品等级结构时,就变成了工厂方法模式。当工厂方法模式
的工厂类只有一个时,且工厂方法为静态方法时,则又变成了简单工厂模式。与工厂方法模式相似,抽象工厂
模式隔离了具体类的生成,让客户端不清楚具体什么样的对象被创建。
抽象⼯⼚模式与⼯⼚⽅法模式虽然主要意图都是为了解决接⼝选择问题,但在实现上抽象⼯⼚是一个中⼼⼯⼚,创
建其他⼯⼚的模式。
相关文章:
Go和Java实现抽象工厂模式
Go和Java实现抽象工厂模式 本文通过简单数据库操作案例来说明抽象工厂模式的使用,使用Go语言和Java语言实现。 1、抽象工厂模式 抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创 建型模式,它…...
深入理解Java虚拟机---内存分配
深入理解Java虚拟机---内存分配 GC日志内存分配与回收策略对象优先在Eden分配大对象直接进入老年代长期存活的对象将进入老年代动态对象年龄判定空间分配担保 GC日志 以下两段典型的GC日志: 33.125: [GC [DefNew: 3324K->152K(3712K), 0.0025925 secs] 3324K-&…...

计算机网络2
OSI参考模型七层: 1.应用层 2.表示层 3.会话层 4.传输层 5.网络层 6.数据链路层 7.物理层 TCP/IP模型 5层参考模型...

jenkins-Generic Webhook Trigger指定分支构建
文章目录 1 需求分析1.1 关键词 : 2、webhooks 是什么?3、配置步骤3.1 github 里需要的仓库配置:3.2 jenkins 的主要配置3.3 option filter配置用于匹配目标分支 实现指定分支构建 1 需求分析 一个项目一般会开多个分支进行开发,测试&#x…...
源码解析8-QSS原理-案例-Qt的qss特殊设置多个子控件的颜色与伪状态
Qt源码解析 索引 源码解析8-QSS原理-案例-Qt的qss特殊设置多个子控件的颜色与伪状态 有些时候我们想特殊设置QSS,比如某一类标题栏目,某一个窗口中的颜色。 重要的是我们需要同时设置多个特殊的按钮等。 统一设置所有 单一按钮全局设置 QPushButton…...

Nginx+Tomcat实现负载均衡和动静分离
目录 前瞻 动静分离和负载均衡原理 实现方法 实验(七层代理) 部署Nginx负载均衡服务器(192.168.75.50:80) 部署第一台Tomcat应用服务器(192.168.75.60:8080) 多实例部署第二台Tomcat应用服务器(192.168.75.70:80…...

linux系统的u盘/mmc/sd卡等的支持热插拔和自动挂载行为
1.了解mdev mdev是busybox自带的一个简化版的udev。udev是从Linux 2.6 内核系列开始的设备文件系统(DevFS)的替代品,是 Linux 内核的设备管理器。总的来说,它取代了 devfs 和 hotplug,负责管理 /dev 中的设备节点。同时…...

使用Python将OSS文件免费下载到本地:项目分析和准备工作
大家好,我是水滴~~ 本文将介绍如何使用Python编程语言将OSS(对象存储服务)中的文件免费下载到本地计算机。我们先进行项目分析和准备工作,为后续的编码及实施提供基础。 《Python入门核心技术》专栏总目录・点这里 文章目录 1. 前…...

从Gitee克隆项目、启动方法
从gitee克隆VUE项目到本地后,不能直接运行,需要进行npm install安装node_modules文件夹里面的内容,因为在git上传的时候,一般都会过滤到node_modules中的依赖文件。 安装依赖以后,启动通过npm run serve启动项目出错。…...

不用再找了,这是大模型实践最全的总结
随着ChatGPT的迅速出圈,加速了大模型时代的变革。对于以Transformer、MOE结构为代表的大模型来说,传统的单机单卡训练模式肯定不能满足上千(万)亿级参数的模型训练,这时候我们就需要解决内存墙和通信墙等一系列问题&am…...
QT 记录
qml 移动窗口会闪烁 int main(int argc, char *argv[]) {QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);//orQCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL); }window 拉取qml程序依赖文件 打开QT自带的命令窗口,转到exe程序目录: …...

智能优化算法应用:基于黑寡妇算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于黑寡妇算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于黑寡妇算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.黑寡妇算法4.实验参数设定5.算法结果6.参考文…...

VSCode 常用的快捷键和技巧系列(2)
一、如何让VSCode工程树显示图标 第一步:安装 快捷键 CtrlP ,输入 ext install vscode-icons ,然后点击安装插件 第二步:配置 安装成功后,点击Reload重新加载。 然后配置,当前图标使用VsCode-Icons Go…...

【Hadoop】执行start-dfs.sh启动hadoop集群时,datenode没有启动怎么办
执行start-dfs.sh后,datenode没有启动,很大一部分原因是因为在第一次格式化dfs后又重新执行了格式化命令(hdfs namenode -format),这时主节点namenode的clusterID会重新生成,而从节点datanode的clusterID 保持不变。 在…...

计算机网络(四)
九、网络安全 (一)什么是网络安全? A、网络安全状况 分布式反射攻击逐渐成为拒绝攻击的重要形式 涉及重要行业和政府部门的高危漏洞事件增多。 基础应用和通用软硬件漏洞风险凸显(“心脏出血”,“破壳”等&#x…...

非递归实现的快速排序
目录 序列文章 前言 学前补充 非递归快速排序 注意事项(重要) 实现步骤 代码实现 时空复杂度 快速排序的特性 栈的相关代码 序列文章 非递归实现的快速排序:http://t.csdnimg.cn/UEcL6 快速排序的挖坑法与双指针法:ht…...

windows 安装jenkins
下载jenkins 官方下载地址:Jenkins 的安装和设置 清华源下载地址:https://mirrors.tuna.tsinghua.edu.cn/jenkins/windows-stable/ 最新支持java8的版本时2.346.1版本,在清华源中找不到,在官网中没找到windows的下载历史ÿ…...

SQL进阶理论篇(十二):InnoDB中的MVCC是如何实现的?
文章目录 简介事务版本号行记录的隐藏列Undo LogRead View的工作流程总结参考文献 简介 在不同的DBMS里,MVCC的实现机制是不同的。本节我们会以InnoDB举例,讲解InnoDB里MVCC的实现机制。 我们需要掌握这么几个概念: 事务版本号行记录的隐藏…...

SpringCloudAliBaba篇之Seata:分布式事务组件理论与实践
1、事务简介 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据库中,一个事务由一组SQL语句组成,事务具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID原则。 原子性(atomici…...

在centos7.9上安装Jenkins的安装过程
1.jenkins的安装和配置: 安装JDK: yum install -y fontconfig java-11-openjdk # 安装目录:/usr/lib/jvm # fontconfig 是 Linux 系统中用于配置和管理字体的一种工具 下载jenkins安装包: sudo wget -O /etc/yum.repos.d/jenkins…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...

算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...