23种设计模式之一————工厂模式详细讲解

工厂模式介绍

  • 定义
  • 分类
  • 工厂模式核心角色:
    • 简单工厂模式
      • 定义
      • 特点
      • 优点
      • 缺点
      • 应用场景
      • 代码实现
    • 工厂方法模式(别名:虚拟构造)
      • 定义
      • 特点
      • 优点
      • 缺点
      • 应用场景
      • 代码实现
    • 抽象工厂模式
      • 定义
      • 特点
      • 优点
      • 缺点
      • 应用场景
      • 代码实现
        • 工厂模式小结

定义

工厂模式属于创建型设计模式,它用于解耦对象的创建和使用。通常情况下,我们创建对象时需要使用new操作符,但是使用new操作符创建对象会使代码具有耦合性。工厂模式通过提供一个公共的接口,使得我们可以在不暴露对象创建逻辑的情况下创建对象。

分类

工厂模式主要分为三种类型:
  简单工厂模式(Simple Factory Pattern)
  工厂方法模式(Factory Method Pattern)
  抽象工厂模式(Abstract Factory Pattern)

工厂模式核心角色:

1.抽象产品(Abstract Product):定义了产品的共同接口或抽象类。它可以是具体产品类的父类或接口,规定了产品对象的共同方法。
2.具体产品(Concrete Product):实现了抽象产品接口,定义了具体产品的特定行为和属性。
3.抽象工厂(Abstract Factory):声明了创建产品的抽象方法,可以是接口或抽象类。它可以有多个方法用于创建不同类型的产品。
4.具体工厂(Concrete Factory):实现了抽象工厂接口,负责实际创建具体产品的对象

简单工厂模式

定义

简单工厂模式是一种创建型设计模式,它提供了一个静态方法(或其他静态机制)来封装对象的创建过程,客户端只需要传入相应的参数,就可以获取到所需要的对象实例,而无需关心具体的创建细节。

特点

1.工厂类包含必要的判断逻辑,根据客户端的请求,决定返回哪一个产品类的实例。
2.客户端只需要知道产品的抽象接口和工厂类,而无需知道具体的产品实现类。
3.将对象的创建与使用解耦,降低了系统的耦合度。

优点

1.客户端无需知道对象的创建细节,只需要知道具体工厂类和对应的参数。
2.将对象的创建和使用分离,使得系统结构更加清晰。
3.提高了系统的可扩展性,当需要增加新的产品时,只需要增加相应的产品类和修改工厂类即可。

缺点

1.工厂类集中了所有产品类的创建逻辑,违反了“单一职责原则”。
2.当产品类族增加时,工厂类的修改和维护会变得复杂。
3.简单工厂模式没有使用面向对象的多态性,而是使用了条件语句来选择要创建的对象,这可能导致系统难以扩展和维护,违反了“开闭原则”(对扩展开放,对修改关闭)。

应用场景

1.当一个系统需要创建的对象较少且创建逻辑相似时,可以考虑使用简单工厂模式。
2.客户端只需要知道传入工厂类的参数,而不关心创建对象的细节时。
3.工厂类负责创建的对象比较少,不会造成工厂方法中的业务逻辑太过复杂。

代码实现

用于根据用户传入的字符串参数(“CIRCLE” 或 “RECTANGLE”)来创建并返回相应的形状对象(Circle 或 Rectangle)。

// 产品接口  
interface Shape {  void draw();  
}    
// 具体产品类 Circle  
class Circle implements Shape {  @Override  public void draw() {  System.out.println("Inside Circle::draw() method.");  }  
}    
// 具体产品类 Rectangle  
class Rectangle implements Shape {  @Override  public void draw() {  System.out.println("Inside Rectangle::draw() method.");  }  
}  
// 工厂类  
class ShapeFactory {  // 使用静态方法创建对象  public static Shape getShape(String shapeType) {  if ("CIRCLE".equalsIgnoreCase(shapeType)) {  return new Circle();  } else if ("RECTANGLE".equalsIgnoreCase(shapeType)) {  return new Rectangle();  }  return null;  }  
}  
// 客户端代码  
public class FactoryPatternDemo {  public static void main(String[] args) {  Shape shape1 = ShapeFactory.getShape("CIRCLE");  shape1.draw();  Shape shape2 = ShapeFactory.getShape("RECTANGLE");  shape2.draw();  }  
}

工厂方法模式(别名:虚拟构造)

定义

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。

特点

1.核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给它的子类去做。
2.客户端针对抽象工厂类编程,不依赖于具体工厂类,符合依赖倒置原则
3.子类可以方便地扩展新的产品类,只需要增加新的具体产品类和对应的具体工厂类,原有工厂类体系不需要做任何修改,符合开闭原则

优点

1.用户只需要知道具体工厂类的名称就可得到所要的产品,无须知道产品的具体类名。
2.通过在工厂接口中定义创建产品的方法,将产品的创建与使用分离,使得系统的扩展性更好。
3.在产品类家族增加新的产品时,只需要增加新的产品类和对应的工厂类,原有系统无须做任何修改,符合“开闭原则”。

缺点

1.当产品类族增加时(即增加一个产品接口和多个实现类),就需要增加一个新的工厂接口和多个具体的工厂实现类,这样会增加系统的复杂度。
2.客户端需要知道新增的工厂接口,并对代码进行修改扩展,在一定程度上增加了客户端的复杂性。

应用场景

1.当一个类不知道它所必须创建的对象的类的时候。
2.当一个类希望由它的子类来指定它所创建的对象的时候。
3.当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者是这一信息局部化的时候。

代码实现

// 产品接口  
interface Product {  void use();  
}  // 具体产品类A  
class ConcreteProductA implements Product {  @Override  public void use() {  System.out.println("Using product A.");  }  
}  // 具体产品类B  
class ConcreteProductB implements Product {  @Override  public void use() {  System.out.println("Using product B.");  }  
}  // 抽象工厂类  
abstract class Creator {  public abstract Product factoryMethod();  
}  // 具体工厂类A  
class ConcreteCreatorA extends Creator {  @Override  public Product factoryMethod() {  return new ConcreteProductA();  }  
}  // 具体工厂类B  
class ConcreteCreatorB extends Creator {  @Override  public Product factoryMethod() {  return new ConcreteProductB();  }  
}  // 客户端代码  
public class FactoryMethodDemo {  public static void main(String[] args) {  Creator creatorA = new ConcreteCreatorA();  Product productA = creatorA.factoryMethod();  productA.use(); // 输出 "Using product A."  Creator creatorB = new ConcreteCreatorB();  Product productB = creatorB.factoryMethod();  productB.use(); // 输出 "Using product B."  }  
}

抽象工厂模式

定义

抽象工厂模式是一种为访问一系列相互关联或相互依赖的对象提供一个接口,而无需指定它们具体的类。在抽象工厂模式中,有一个抽象工厂接口定义了创建产品对象的操作接口,但由子类来决定实例化哪一个类。客户端则针对抽象工厂接口编程,不依赖于具体的工厂实现。

特点

1.抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。
2.将一个系列的产品族统一到一起创建。
3.每一个产品族都有一个具体的工厂,负责创建具体产品对象。

优点

1.易于交换产品系列,由于一个具体的工厂类只在一个产品族中创建产品对象,使得将一个产品族替换成另一个产品族变得容易,它只需要改变具体的工厂类即可。
2.有利于产品的一致性,当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
3.提高系统的可扩展性,增加新的产品族很方便,无需修改已有的系统,符合开闭原则。

缺点

1.抽象工厂模式增加了系统的抽象性和理解难度,不易于理解和修改;
2.新增产品族时需要修改工厂接口、工厂实现类和产品类,增加了系统的复杂性。

应用场景

1.当一个系统需要独立地变化产品的族时。
2.当系统需要多个产品族,并且这些产品族之间是相互关联的。
3.当需要创建复杂对象时,抽象工厂模式可以简化创建过程。

代码实现

// 产品接口A  
interface ProductA {  void use();  
}  // 产品接口B  
interface ProductB {  void assemble();  
}  // 产品A的实现类1  
class ConcreteProductA1 implements ProductA {  @Override  public void use() {  System.out.println("Using product A1.");  }  
}  // 产品A的实现类2  
class ConcreteProductA2 implements ProductA {  @Override  public void use() {  System.out.println("Using product A2.");  }  
}  // 产品B的实现类1  
class ConcreteProductB1 implements ProductB {  @Override  public void assemble() {  System.out.println("Assembling product B1.");  }  
}  // 产品B的实现类2  
class ConcreteProductB2 implements ProductB {  @Override  public void assemble() {  System.out.println("Assembling product B2.");  }  
}  // 抽象工厂接口  
interface AbstractFactory {  ProductA createProductA();  ProductB createProductB();  
}  // 具体工厂类1  
class ConcreteFactory1 implements AbstractFactory {  @Override  public ProductA createProductA() {  return new ConcreteProductA1();  }  @Override  public ProductB createProductB() {  return new ConcreteProductB1();  }  
}  // 具体工厂类2  
class ConcreteFactory2 implements AbstractFactory {  @Override  public ProductA createProductA() {  return new ConcreteProductA2();  }  @Override  public ProductB createProductB() {  return new ConcreteProductB2();  }  
}  // 客户端代码  
public class Client {  public static void main(String[] args) {  AbstractFactory factory1 = new ConcreteFactory1();  ProductA productA1 = factory1.createProductA();  ProductB productB1 = factory1.createProductB();  productA1.use();  productB1.assemble();  AbstractFactory factory2 = new ConcreteFactory2();  ProductA productA2 = factory2.createProductA();  ProductB productB2 = factory2.createProductB();  productA2.use();  productB2.assemble();  }  
}
工厂模式小结

工厂方法模式与抽象工厂模式的区别在于:
1)工厂方法只有一个抽象产品类和一个抽象工厂类,但可以派生出多个具体产品类和具体工厂类,每个具体工厂类只能创建一个具体产品类的实例;
2)抽象工厂模式拥有多个产品类(产品族)和一个抽象工厂类,每个抽象产品类可以派生出多个具体产品类;抽象工厂类也可以派生出多个具体工厂类,同时每个具体工厂类可以创建多个具体产品类的实例。

博主用心写,读者点关注;互动传真情,知识不迷路。

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

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

相关文章

算法之背包问题

可分的背包问题是可以用贪心法来解决,而0-1背包问题通常使用动态规划方法来解决。 可分背包问题: 在可分背包问题中,物品可以被分割,您可以取走物品的一部分以适应背包的容量。这里的关键是物品的价值密度,即单…

最小产品价格差值

题目描述 给定某产品多少天的价格,记录于prices中,请找出任意两天之间的最小价格差(即abs(prices[i] - prices[j]))的最小值,i!j)并计算最小介个差组合的个数 样例1 输入 [1,3,7,5,12] 输出 3 样例2…

VTK9.2.0+QT5.14.0绘制三维显示背景

背景 上一篇绘制点云的博文中,使用的vtkCameraOrientationWidget来绘制的坐标轴,最近又学习到两种新的坐标轴绘制形式。 vtkOrientationMarkerWidget vtkAxesActor 单独使用vtkAxesActor能够绘制出坐标轴,但是会随着鼠标操作旋转和平移时…

微服务中使用Maven BOM来管理你的版本依赖

摘要: 原创出处 sf.gg/a/1190000021198564 「飘渺Jam」欢迎转载,保留摘要,谢谢! 为什么要使用BOM? 如何定义BOM? 项目使用方法? BOM(Bill of Materials)是由Maven提供的功能,它通过定义一整套相互兼容的jar包版…

通过 NIO + 多线程 提升硬件设备与系统的数据传输性能

一、项目展示 下图(模拟的数据可视化大屏)中数据是动态显示的 二、项目简介 描述:使用Client模拟了硬件设备,比如可燃气体浓度检测器。Client通过Socket与Server建立连接,Server保存数据到txt文件,并使用W…

结构体(位段)内存分配

结构体由多个数据类型的成员组成。那编译器分配的内存是不是所有成员的字节数总和呢? 首先,stu的内存大小并不为29个字节,即证明结构体内存不是所有成员的字节数和。   其次,stu成员中sex的内存位置不在21,即可推测…

Swift 请求用户授权以跟踪其跨应用或网站的活动

步骤1:导入框架 首先,需要在Swift文件中导入AppTrackingTransparency框架。 import AppTrackingTransparency import AdSupport步骤2:请求跟踪许可 在适当的地方请求用户的跟踪许可。通常,这个请求会在应用启动时或者在用户执行某些操作(例如,访问应用中的广告相关功能…

Linux服务器安装docker,基于Linux(openEuler、CentOS8)

本实验环境为openEuler系统(以server方式安装)(CentOS8基本一致,可参考本文) 目录 知识点实验 知识点 Docker 是一个开源的应用容器引擎。它允许开发者将应用及其所有依赖项打包到一个可移植的容器中,并发布到任何支持Docker的流行Linux或Wi…

基于python flask的web服务

基本例子 from flask import Flask app Flask(__name__) app.route(/)#检查访问的网址,根路径走这里 def hello_world():return hello world#返回hello worldif __name__ __main__:# 绑定到指定的IP地址和端口app.run(host0.0.0.0, port1000, debugTrue)##绑定端…

设计一个完美的用户角色权限表

设计一个完美的用户角色权限表需要考虑系统的安全性、灵活性和可扩展性。以下是一个详细的用户角色权限管理表设计方案,包含多个表结构和字段描述。 目录 1. 用户表(Users Table)2. 角色表(Roles Table)3. 权限表&…

【数据结构与算法 | 基础篇】环形数组模拟队列

1. 前言 上文我们用环形单向链表实现了队列.接下来我们用环形数组来模拟队列.并实现了isFull()&#xff0c;isEmpty()等方法. 2. 环形数组模拟队列 (1). Queue接口 : public interface Queue<E> {//向队伍插入值, 插入成功返回true, 否则返回falseboolean offer(E v…

【Linux】TCP协议【上】{协议段属性:源端口号/目的端口号/序号/确认序号/窗口大小/紧急指针/标记位}

文章目录 1.引入2.协议段格式4位首部长度16位窗口大小32位序号思考三个问题【demo】标记位URG: 紧急指针是否有效提升某报文被处理优先级【0表示不设置1表示设置】ACK: 确认号是否有效PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走RST: 对方要求重新建立连接; 我们把携带R…

windows 设置系统字体 (win11 win10)

由于微软的字体是有版权的&#xff0c;所以我打算替换掉 1.下载替换工具 github的项目&#xff0c;看起来很多人对微软默认字体带版权深恶痛绝。 项目地址&#xff1a;nomeiryoUi地址 这里选取最新的版本即可 2.打开软件 这里显示标题栏不能改&#xff0c;确认&#xff0c;其…

盖雅技能发展云,助力制造企业人效合一

制造行业尽管经历多次变革&#xff0c;但企业对人的管理始终是一项高度依赖经验和耗费人力的工作。随着供应链管理和生产设备的自动化、数字化升级&#xff0c;如何将第一生产要素——人&#xff0c;通过数字化的工具融入制造过程的闭环&#xff0c;对企业实现自动化工厂和智能…

力扣 滑动窗口题目总结

Leetcode3.无重复字符的最长子串 思路&#xff1a; 这道题主要用到思路是&#xff1a;滑动窗口 什么是滑动窗口&#xff1f; 其实就是一个队列,比如例题中的 abcabcbb&#xff0c;进入这个队列&#xff08;窗口&#xff09;为 abc 满足题目要求&#xff0c;当再进入 a&#x…

牛客NC334 字典序第K小【困难 10叉树 Java/Go/PHP/C++】,力扣 440. 字典序的第K小数字

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/670c2bda374241d7ae06ade60de33e8b https://leetcode.cn/problems/k-th-smallest-in-lexicographical-order/description/ 本答案核心 10叉树, 数学规律Java代码 import java.util.*;public class Solution {…

大模型的灵魂解读:Anthropic AI的Claude3 Sonnet可解释性研究

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调重新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则提供了大模型领域最新技…

Vue集成Iframe

一、应用场景&#xff0c;为什么要集成Iframe&#xff1f; 1、庞大项目拆分后&#xff0c;便于管理和部署&#xff0c;用集成Iframe的方法合并 2、避免功能重复开发&#xff0c;共用模块可单独开发为一个项目&#xff0c;既可独立部署&#xff0c;也可集成到中台系统 二、集成…

[算法][前缀和] [leetcode]724. 寻找数组的中心下标

题目地址 https://leetcode.cn/problems/find-pivot-index/description/ 题目描述 代码 class Solution {public int pivotIndex(int[] nums) {int total Arrays.stream(nums).sum();//前缀和int prefixSum 0;int len nums.length;for(int i 0;i<len;i){if (i-1>0){p…

小猪APP分发:一站式托管服务,轻松玩转应用市场

在当今移动应用爆炸式增长的时代&#xff0c;开发者们面临的挑战不再仅限于创意的火花和代码的实现&#xff0c;更在于如何让精心打造的应用快速触达广大用户。这正是小猪APP分发www.appzhu.net应运而生的背景——作为一个全面、高效的APP托管服务分发平台&#xff0c;它为开发…