工厂模式简介

概念

工厂模式(Factory Pattern)是一种创建型设计模式,它提供了一种封装对象实例化过程的方式,客户端只需要关注接口或抽象类,并由工厂类根据具体需求返回相应的实例。工厂模式将对象的创建与使用分离,客户端无需直接调用构造函数来创建对象。工厂模式定义了一个抽象工厂和多个具体工厂,每个具体工厂负责创建特定类型的产品。

特点

  1. 封装性:隐藏了对象实例化细节,客户端只需要与抽象接口交互。
  2. 扩展性:易于添加新产品或变更现有产品的实现。
  3. 解耦性:将客户端与具体产品之间解耦,降低了代码依赖关系。

优点

  1. 符合开闭原则:新增产品时无需修改已有代码,在扩展上更加灵活。
  2. 降低耦合度:客户端仅依赖于抽象接口而非具体实现类。
  3. 高内聚、低耦合:相关逻辑被封装在各自的具体工厂中。

缺点

  1. 增加系统复杂度:引入额外的类和层级,增加了代码量。
  2. 需要额外的工厂类:每个具体产品都需要对应一个具体工厂类。

适用场景

  1. 需要创建多个相似对象的场景。
  2. 客户端不关心实例化过程和细节,只需获取抽象接口即可的场景。

实现方式

简单工厂模式

实现原理:

  1. 定义一个接口或父类来表示产品。
  2. 创建具体产品类,它们继承自父类或实现接口。
  3. 创建一个简单工厂类,该类包含一个静态方法用于根据客户端传入的参数来创建相应的具体产品对象。

实现代码:

// 接口或父类
interface Product {void doSomething();
}// 具体产品A
class ConcreteProductA implements Product {@Overridepublic void doSomething() {System.out.println("ConcreteProductA do something");}
}// 具体产品B
class ConcreteProductB implements Product {@Overridepublic void doSomething() {System.out.println("ConcreteProductB do something");}
}// 简单工厂类
public class SimpleFactory {// 静态方法根据参数创建对应的具体产品对象public static Product createProduct(String type) {if (type.equals("A")) { return new ConcreteProductA();} else if (type.equals("B")) { return new ConcreteProductB();} else { throw new IllegalArgumentException("Invalid product type.");}}public static void main(String[] args){Product a = SimpleFactory.createProduct("A");a.doSomething();}
}

上述代码中,我们定义了一个 Product 接口作为抽象基类,然后创建了两个具体产品类 ConcreteProductA  ConcreteProductB,它们都实现了 Product 接口。最后,我们创建了一个简单工厂类 SimpleFactory,其中的静态方法根据客户端传入的参数来创建相应的具体产品对象。使用简单工厂模式时存在以下问题:

  1. 违反开闭原则:每次添加新产品都需要修改工厂类中的代码。
  2. 工厂职责过重:所有产品的创建逻辑集中在一个工厂类中,导致该类变得庞大而复杂。

尽管简单工厂模式存在以上问题,但它仍然是一种常用且易于理解和实现的工厂模式。

工厂方法模式

实现原理:

  1. 定义一个接口或父类来表示产品。
  2. 创建具体产品类,它们继承自父类或实现接口。
  3. 创建一个抽象工厂接口,该接口声明了创建产品的方法。
  4. 创建多个具体工厂类,每个具体工厂类负责创建特定类型的产品。

实现代码:

// 接口或父类
interface Product {void doSomething();
}// 具体产品A
class ConcreteProductA implements Product {@Overridepublic void doSomething() {System.out.println("ConcreteProductA do something");}
}// 具体产品B
class ConcreteProductB implements Product {@Overridepublic void doSomething() {System.out.println("ConcreteProductB do something");}
}// 抽象工厂接口
interface Factory {Product createProduct();
}// 具体工厂A用于创建具体产品A
class ConcreteFactoryA implements Factory {@Overridepublic Product createProduct() {return new ConcreteProductA();}
}// 具体工厂B用于创建具体产品B 
class ConcreteFactoryB implements Factory {@Override public Product createProduct() { return new ConcreteProductB();}
}

上述代码中,我们定义了一个 Product 接口作为抽象基类,然后创建了两个具体产品类 ConcreteProductA  ConcreteProductB,它们都实现了 Product 接口。接着,我们定义了一个抽象工厂接口 Factory,其中声明了一个用于创建产品的方法。最后,我们创建了两个具体工厂类 ConcreteFactoryA  ConcreteFactoryB,分别用于创建具体产品 A B

使用工厂方法模式时存在以下问题:

  1. 每次添加新产品需要同时增加对应的具体工厂类。
  2. 客户端需要知道不同的具体工厂类来获取不同类型的产品。

尽管存在以上问题,但工厂方法模式能够提供更好的扩展性和灵活性,并且符合开闭原则。客户端只需关注与特定的抽象工厂和产品进行交互即可。

抽象工厂模式

实现原理:

  1. 定义产品族接口,该接口声明了一组相关的产品。
  2. 创建多个具体产品族类,每个具体产品族类负责实现对应的抽象产品族接口。
  3. 定义抽象工厂接口,该接口声明了用于创建不同产品族对象的方法。
  4. 创建多个具体工厂类,每个具体工厂类负责创建特定类型的产品族对象。

实现代码:

//产品A
interface ProductA {void doSomething();
}// 具体产品A1
class ConcreteProductA1 implements ProductA {@Overridepublic void doSomething() {System.out.println("ConcreteProductA1 do something");}
}// 具体产品A2
class ConcreteProductA2 implements ProductA {@Overridepublic void doSomething() {System.out.println("ConcreteProductA2 do something");}
}// 抽象产品B 
interface ProductB { void doSomething(); 
} // 具体产品B1 
class ConcreateProductB1 implements ProductB { @Override public void doSomething() { System.out.println("ConcreteProductB1 do something"); } 
} // 具体产品B2 
class ConcreateProductB2 implements ProductB { @Override public void doSomething() { System.out.println("ConcreteProductB2 do something"); } 
}// 抽象工厂接口
interface AbstractFactory {ProductA createProductA();ProductB createProductB();
}// 具体工厂1用于创建具体产品族1
class ConcreteFactory1 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA1();}@Overridepublic ProductB createProductB() {return new ConcreateProductB1();}
}// 具体工厂2用于创建具体产品族2
class ConcreteFactory2 implements AbstractFactory {@Override  public ProductA createProductA() {  return new ConcreteProductA2();  }  @Override   public ProductB createProductB() {   return new ConcreateProductB2();   }  
}

上述代码中,我们定义了两个产品接口 ProductA  Prodcut B,并分别实现了它们的具体产品类。然后,我们定义了一个抽象工厂接口 AbstractFactory,其中声明了两个方法用于创建不同类型的抽象产品对象。最后,我们创建了两个具体工厂类 ConcreteFactory1  ConcreteFactory2 分别负责创建特定的抽象产品族对象。

使用抽象工厂模式时存在以下问题:

  1. 每次添加新产品族需要同时增加对应的产品接口和具体产品类。
  2. 客户端需要知道不同的具体工厂类来获取不同类型的抽象产品。

尽管存在以上问题,但抽象工厂模式能够提供更好的扩展性和灵活性,并且符合开闭原则。客户端只需关注与特定的抽象工厂和产品进行交互即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/56202.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux下jenkins全量迁移到新服务器

文章目录 1、目的2、迁移1)查看jenkins的主目录2)登录要迁出的服务器打包3)找到对应的war包4)登录对应迁入服务,上传war包和打包的jenkins数据等5)在新的服务器解压迁入的数据等,并查看端口是否…

vue和react学哪一个比较有助于以后发展?

前言 首先声明vue和react这两个框架都是很优秀的前端框架,使用的人群下载量上数量也是相当的庞大,这篇文章没有贬低或者攻击任何一个框架的意思,只在于根据答主的问题来对这两个框架做出对比,以方便大家更加清晰的了解到当下vue和…

邂逅JavaScript

前言:前端三大核心 前端开发最主要需要掌握的是三个知识点:HTML、CSS、JavaScript 一、认识编程语言 1.计算机语言 前面我们已经学习了HTML和CSS很多相关的知识: 在之前我们提到过, HTML是一种标记语言, CSS也是一种样式语言; 他们本身都是属于计算…

4、Spring之Bean生命周期源码解析(创建)

Spring最重要的功能就是帮助程序员创建对象(也就是IOC),而启动Spring就是为创建Bean对象做准备,所以我们先明白Spring到底是怎么去创建Bean的,也就是先弄明白Bean的生命周期。 Bean的生命周期就是指:在Spring中,一个Bean是如何生成的,如何销毁的。 Bean生命周期流程图…

k3s在线快速安装部署

中文文档:快速入门指南 | K3s 一、k3s父节点安装 设置主机唯一名称 hostnamectl set-hostname 192.168.56.105 开放k3s所需端口 6443 51820 和 51821 在线安装主节点 curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRRORcn…

剑指 Offer 60. n个骰子的点数

剑指 Offer 60. n个骰子的点数 动态规划:已知n-1个骰子的所有情况,再增加一个骰子,可推出n个骰子的所有情况。增加的一个骰子的点数只有1-6种可能,与n-1个骰子对应点数相乘,可得到n个骰子点数的一种情况,遍…

Java学习

程序计数器 Program Counter Register:  记录的是正在执行的虚拟机字节码指令的地址,  此内存区域是唯一一个在JAVA虚拟机规范中没有规定任何OutOfMemoryError的区 域 虚拟机:VM Stack  描述的是 JAVA 方法执行的内存模型,每…

通道洗牌操作

假设我们有一个4通道的2x2的图像(batch size为1),即b1, c4, hw2,并且我们选择groups2,那么我们将通道分为两组。 给定以下输入x: x [[[1, 2], [3, 4]],[[5, 6], [7, 8]],[[9, 10], [11, 12]],[[13, 14],[15, 16]] ]首先&…

Python第三方库纵览

Python第三方库纵览 知识点 更广泛的Python计算生态,只要求了解第三方库的名称,不限于以下领域: 网络爬虫、数据分析、文本处理、数据可视化、用户图形界面、机器学习、Web开发、游戏开发等 知识导图 1、网络爬虫方向 网络爬虫是自动进行HTTP访问并捕…

数学分析:场论

我们之前知道的是里斯表示定理。 这里看到,对于多重线性映射,里斯表示定理会从内积变成混合积。当然我们还是只考虑三维以内的情况。 于是我们可以把不同的1形式和2形式的下标写上,表示他们相当于内积或者混合积对应的那个向量。 然后还差0形…

怎么把PDF转成Word?需要注意什么事项?

PDF是一种常见的文档格式,但是与Word文档不同,PDF文件通常不能直接编辑。如果您想编辑PDF文件中的文本,或者想将PDF文件转换为Word文档,下面我们就来看一看把PDF转成Word有哪些方法和注意事项。 PDF转Word工具 有许多将PDF转换为…

【vue+uniapp】切换本页面(点击导航按钮)就刷新接口

查阅资料:uni-app官网 点击导航中图标,就执行的方法(和methods同级): onTabItemTap(e) {this.getTaskTotal(); },

Java 版 spring cloud 工程系统管理 工程项目管理系统源码 工程项目各模块及其功能点清单

工程项目各模块及其功能点清单 一、系统管理 1、数据字典:实现对数据字典标签的增删改查操作 2、编码管理:实现对系统编码的增删改查操作 3、用户管理:管理和查看用户角色 4、菜单管理:实现对系统菜单的增删改查操…

跳跃游戏【贪心算法】

跳跃游戏 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。在这里插入图片…

docker 部署服务

1、使用mysql:5.6和 owncloud 镜像,构建一个个人网盘。 [rootbogon ~]# docker pull mysql:5.6 [rootbogon ~]# docker pull owncloud [rootbogon ~]# docker run -itd --name mysql --env MYSQL_ROOT_PASSWORD123456 mysql:5.6 [rootbogon ~]# docker run -itd -…

AI 绘画Stable Diffusion 研究(十六)SD Hypernetwork详解

大家好,我是风雨无阻。 本期内容: 什么是 Hypernetwork?Hypernetwork 与其他模型的区别?Hypernetwork 原理Hypernetwork 如何下载安装?Hypernetwork 如何使用? 在上一篇文章中,我们详细介绍了 …

xxl-job学习(一遍文章解决)

前言:学习xxl-job需要有git,springboot的基础,学起来就很简单 xxl-job是一个分布式的任务调度平台,其核心设计目标是:学习简单、开发迅速、轻量级、易扩展,现在已经开放源代码并接入多家公司的线上产品线&a…

AWS 提示证书签名过期无法自动更新

如果域名没有通过验证的话,证书的过去是没有办法自动更新的。 验证的方式也非常简单,通过下面的配置,把 CNAME添加到你的域名上面,AWS 就可会自动完成验证了。 当添加完成后,AWS 验证需要的时间大致在 30 分钟到 1 个…

bindService的调用流程

使用bindService去调用service,如果有多个客户端调用,onBind方法只会被调用一次,由于bindService嗲处理中,AMS是一个中间商,猜测这个处理也是AMS里进行的,这里我们再看看bindService的调用流程 public clas…

C#基础进阶

C#基础进阶 泛型 http://www.runoob.com/csharp/csharp-generic.html 匿名函数 http://www.runoob.com/csharp/csharp-anonymous-methods.html 扩展方法 https://blog.csdn.net/u011127019/article/details/54728886 https://docs.microsoft.com/zh-cn/dotnet/csharp/pr…