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…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

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