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…...

uni-app基本标签
导航栏设置 - navigationBarBackgroundColor: 设置导航栏的背景颜色(全局页面) - navigationBarTextStyle: 导航栏标题颜色(仅支持 black 和 white) - navigationBarTitleText: 设置导航栏标题内容 - enablePullDownRefresh: 是否…...

《PySpark大数据分析实战》-14.云服务模式Databricks介绍基本概念
📋 博主简介 💖 作者简介:大家好,我是wux_labs。😜 热衷于各种主流技术,热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员(PCTA)、TiDB数据库专家(PCTP…...

微信小程序校园跑腿系统怎么做,如何做,要做多久
在这个互联网快速发展、信息爆炸的时代,人人都离不开手机,每个人都忙于各种各样的事情,大学生也一样,有忙于学习,忙于考研,忙着赚学分,忙于参加社团,当然也有忙于打游戏的&#x…...

当我分别问8款GPT一个问题。。。
前两天下班在地铁上无聊寻思问一下不同的GPT一个相同的问题,哪个会给出我比较满意的答案,然后我就提问:我老妹有点憨怎么办?(ps:开玩笑的,嘻嘻。。。) 很明显其他GPT都给出了大差不差…...

Elasticsearch 8.9 search命令执行查询源码
一、相关的API的handler1、接收HTTP请求的handler2、往数据节点发送查询请求的action(TransportSearchAction)3、通过transportService把查询请求发送到指定的数据节点 二、数据节点收到请求的处理逻辑1、尝试从缓存中加载查询结果2、不通过缓存查询,直接执行查询(1…...

【PHP】身份证正则验证、校验位验证
目录 1.正则 简单正则 详细正则 2.校验位验证 1.正则 简单正则 function isValidIdCardNumber($idCardNumber) {// 身份证号长度为 15 位或 18 位$pattern /^(?:\d{15}|\d{17}[\dxX])$/;return preg_match($pattern, $idCardNumber); }$idCardNumber 12345678901234567…...

Matlab示例-Examine 16-QAM Using MATLAB学习笔记
工作之余学习16-QAM 写在前面 网上看到许多示例,但一般都比较难以跑通。所以,还是老方法,先将matlab自带的例子研究下。 Examine 16-QAM Using MATLAB Examine 16-QAM Using MATLAB 或者,在matlab中,键入&#x…...

ArcGIS Pro SDK运行消息只提示一次
工具大部分都是异步执行,所以提示信息需要异步执行完再进行,所以注意async和await的使用。 相关async和await的文章请查看C# 彻底搞懂async/await_c# async await-CSDN博客 public async Task InformationPrompt() {string message String.Empty;await ArcGIS.De…...

通话状态监听-Android13
通话状态监听-Android13 1、Android Telephony 模块结构2、监听和广播获取通话状态2.1 注册2.2 通话状态通知2.3 通话状态 3、通知状态流程* 关键日志 frameworks/base/core/java/android/telephony/PhoneStateListener.java 1、Android Telephony 模块结构 Android Telephony…...

无懈可击的防泄密之旅:迅软DSE在民营银行的成功实践
客户简要介绍 某股份有限公司主体是中部地区的民营银行,由其母公司联合9家知名民营企业共同发起设立。正式开业于2016年,紧紧围绕目标产业生态圈和消费金融,着力打造产业银行、便捷银行、数字银行、财富管理银行为一体的BEST银行,…...