简谈设计模式之工厂模式

工厂模式是一种创建型设计模式, 旨在将对象的创建过程和使用过程分离. 这样可以在不改变客户端代码的前提下, 灵活创建不同类型的对象

工厂模式实现
  1. 简单工厂模式

简单工厂模式使用一个工厂类根据传入的参数决定创建哪种具体产品类的实例. 它不属于设计模式的23种, 但它为理解工厂模式奠定了基础

// 产品接口
interface Product {void use();
}// 具体产品A
class ConcreateProductA implements Product {public void use() {System.out.println("Using product A");}
}// 具体产品B
class ConcreateProductB implements Product {public void use() {System.out.println("Using product B");}
}// 简单工厂类
class SimpleFactory {public static Product createProduct(String type) {if (type.equals("A")) {return new ConcreateProductA();} else if (type.equals("B")) {return new ConcreateProductB();} else {throw new IllegalArgumentException("Unknown product type");}}
}// 客户端代码
public class Client {public static void main(String[] args) {Product productA = SimpleFactory.createProduct("A");productA.use();Product produceB = SimpleFactory.createProduct("B");productB.use();}
}

优点: 封装了创建对象的流程, 可以通过参数直接获取对象, 把对象的创建和业务逻辑层分开, 这样以后就避免了修改客户端代码. 如果要实现新产品直接修改工厂类, 而不需要在源代码中修改, 这样就降低了客户代码修改的可能性, 更容易拓展

缺点: 增加新产品时还需要修改工厂类的代码, 违背了开闭原则

  1. 工厂方法模式

工厂方法模式使用工厂接口定义一个创建对象的接口, 但由子类决定实例化哪个类, 这样工厂方法模式使得一个类的实例延迟到其子类

// 产品接口
interface Product {void use();
}// 具体产品A
class ConcreateProductA implements Product {public void use() {System.out.println("Using product A");}
}// 具体产品B
class ConcreateProductB implements Product {public void use() {System.out.println("Using product B");}
}// 工厂接口
interface Factory {Product createProduct();
}// 具体工厂A
class ConcreteFactoryA implements Factory {public Product createProduct() {return new ConcreteProductA();}
}// 具体工厂A
class ConcreteFactoryB implements Factory {public Product createProduct() {return new ConcreteProductB();}
}// 客户端代码
public class Client {public static void main(String[] args) {Factory factoryA = new ConcreteFactoryA();Product productA = factoryA.createProduct();productA.use();Factory factoryB = new ConcreteFactoryB();Product productB = factoryB.createProduct();productB.use();}
}

优点:

  • 用户只需要知道具体工厂的名称就能得到所要的产品, 不需要知道产品的具体创建过程
  • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类, 无须对原工厂进行任何修改, 满足开闭原则

缺点: 每增加一个产品就要增加一个具体产品类和具体工厂类, 增加了系统复杂度

  1. 抽象工厂模式

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口, 而无需指定它们具体的类. 通过定义多个工厂接口来实现不同产品族的创建

// 产品A接口
interface ProductA {void use();
}// 产品B接口
interface ProductB {void eat();
}// 具体产品A1
class ConcreteProductA1 implements ProductA {public void use() {System.out.println("Using product A1");}
}// 具体产品A2
class ConcreteProductA2 implements ProductA {public void use() {System.out.println("Using product A2");}
}// 具体产品B1
class ConcreteProductB1 implements ProductB {public void eat() {System.out.println("Eating product B1");}
}// 具体产品B2
class ConcreteProductB2 implements ProductB {public void eat() {System.out.println("Eating product B2");}
}// 抽象工厂接口
interface AbstractFactory {ProductA createProductA();ProductB createProductB();
}// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {public ProductA createProductA() {return new ConcreteProductA1();}public ProductB createProductB() {return new ConcreteProductB1();}
}// 具体工厂2
class ConcreteFactory2 implements AbstractFactory {public ProductA createProductA() {return new ConcreteProductA2();}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.eat();AbstractFactory factory2 = new ConcreteFactory2();ProductA productA2 = factory2.createProductA();ProductB productB2 = factory2.createProductB();productA2.use();productB2.eat();}
}

工厂方法模式与抽象工厂模式的区别

  1. 复杂性和用途
    • 工厂方法模式: 创建一个具体产品对象, 适合于一个产品等级结构
    • 抽象工厂模式: 创建一系列相关或相互依赖的对象, 适合于多个产品等级结构
  2. 类结构
    • 工厂方法模式: 只有一个抽象产品类和多个具体产品类, 以及一个抽象工厂类和多个具体工厂类
    • 抽象工厂模式: 有多个抽象产品类和多个具体产品类, 以及一个抽象工厂类和多个具体工厂类
  3. 拓展性:
    • 工厂方法模式: 增加新的产品需要增加新的具体产品类和具体工厂类
    • 抽象工厂模式: 增加新的产品族需要增加新的具体工厂类, 增加新的产品等级需要增加修改所有的工厂类

优点: 当一个产品族中的多个对象被设计在一起工作时, 它能保证客户端始终使用同一个产品族中的对象

缺点: 当产品族中需要添加一个新产品时, 所有的工厂类都需要修改

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

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

相关文章

数字电路-建立时间和保持时间详解

对于数字系统而言,建立时间(setup time)和保持时间(hold time)是数字电路时序的基础。数字电路系统的稳定性,基本取决于时序是否满足建立时间和保持时间。我自己在初学时一度很难理解清楚他们的概念&#x…

云端典藏:iCloud中个人收藏品目录的智能存储方案

云端典藏:iCloud中个人收藏品目录的智能存储方案 在数字化生活不断推进的今天,个人收藏品的管理也趋向于电子化和云端化。iCloud作为苹果公司提供的云服务,为个人收藏品目录的存储和管理提供了一个安全、便捷、跨设备的解决方案。本文将详细…

0145__Linux的capability

https://zhuanlan.zhihu.com/p/693896673 Linux的capability深入分析(1)_linux 设置进程capprm-CSDN博客 cap_init(3) - Linux manual page

【异常错误】Compile with `TORCH_USE_CUDA_DSA` to enable device-side assertions.

在运行项目的时候&#xff0c;出现了错误&#xff0c;但是却不知道为什么错误&#xff0c;因为GPU报的错误太抽象 ../aten/src/ATen/native/cuda/Indexing.cu:1239: indexSelectSmallIndex: block: [5,0,0], thread: [82,0,0] Assertion srcIndex < srcSelectDimSize failed…

基于JAVA+SpringBoot+Vue+uniApp小程序的心理健康测试平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 该系统由三个核心角色…

维度评分:Kylin Cube设计中的自定义智能

维度评分&#xff1a;Kylin Cube设计中的自定义智能 引言 Apache Kylin是一个高性能的分布式分析引擎&#xff0c;它通过构建数据立方体&#xff08;Cube&#xff09;来加速对大数据集的查询。在Kylin中&#xff0c;维度的自定义评分是一个高级特性&#xff0c;允许用户根据业…

【PVE】新增2.5G网卡作为主网卡暨iperf测速流程

【PVE】新增2.5G网卡作为主网卡暨iperf测速流程 新增网卡 新增网卡的首先当然需要关闭PVE母机&#xff0c;把新网卡插上&#xff0c;我用淘宝遥现金搞了个红包&#xff0c;花了26元买了块SSU的2.5G网卡。说实话这个价位连散热片都没有&#xff0c;确实挺丐的。稍后测下速度看…

移动硬盘有盘符打不开的全方位解决方案

一、现象描述&#xff1a;移动硬盘有盘符却无法访问 在日常的数据存储与传输中&#xff0c;移动硬盘无疑扮演着举足轻重的角色。然而&#xff0c;不少用户可能会遇到这样一个令人头疼的问题&#xff1a;移动硬盘在连接电脑后&#xff0c;虽然能正常显示盘符&#xff0c;但双击…

【算法】单调队列

一、什么是单调队列 单调队列是一种数据结构&#xff0c;其特点是队列中的元素始终保持单调递增或递减&#xff0c;主要用于维护队列中的最小值或最大值。 不同于普通队列只能从队头出队、队尾入队&#xff0c;单调队列为了维护其特征&#xff0c;还允许从队尾出队 不管怎么…

深入Linux:权限管理与常用命令详解

文章目录 ❤️Linux常用指令&#x1fa77;zip/unzip指令&#x1fa77;tar指令&#x1fa77;bc指令&#x1fa77;uname指令&#x1fa77;shutdown指令 ❤️shell命令以及原理❤️什么是 Shell 命令❤️Linux权限管理的概念❤️Linux权限管理&#x1fa77;文件访问者的分类&#…

【微信小程序知识点】getApp()全局数据共享,页面间通信,组件间通信

getApp()-全局数据共享 在小程序中&#xff0c;可以通过getApp()方法获取到小程序全局唯一的App实例。因此在App()方法中添加全局共享的数据&#xff0c;方法&#xff0c;从而实现页面&#xff0c;组件的数据传值。 // app.js App({//全局共享的数据globalData: {token: &qu…

力扣每日一题:3011. 判断一个数组是否可以变为有序

力扣官网&#xff1a;前往作答&#xff01;&#xff01;&#xff01;&#xff01; 今日份每日一题&#xff1a; 题目要求&#xff1a; 给你一个下标从 0 开始且全是 正 整数的数组 nums 。 一次 操作 中&#xff0c;如果两个 相邻 元素在二进制下数位为 1 的数目 相同 &…

Cxx Primer-CP-2

开篇第一句话足见作者的高屋建瓴&#xff1a;类型决定程序中数据和操作的意义。随后列举了简单语句i i j;的意义取决于i和j的类型。若它们都是整形&#xff0c;则为通常的算术意义。若它们都为字符串型&#xff0c;则为进行拼接操作。若为用户自定义的class类型&#xff0c;则…

为Linux设置GRUB密码

正文共&#xff1a;999 字 11 图&#xff0c;预估阅读时间&#xff1a;1 分钟 我们前面介绍了如何恢复root密码&#xff08;CentOS 7.9遗忘了root密码怎么办&#xff1f;&#xff09;&#xff0c;虽然简单好用&#xff0c;但是可能会被不法分子利用&#xff0c;造成root密码以及…

快速读出linux 内核中全局变量

查问题时发现全局变量能读出来会提高效率&#xff0c;于是考虑从怎么读出内核态的全局变量&#xff0c;脚本如下 f open("/proc/kcore", rb) f.seek(4) # skip magic assert f.read(1) b\x02 # 64 位def read_number(bytes):return int.from_bytes(bytes, little,…

【DDD】领域驱动设计概念深入探索

一、DDD核心理念的深入探索 1.1 业务领域的全方位理解 业务专家的深度参与&#xff1a;业务专家不仅仅是项目的顾问&#xff0c;他们是项目团队不可或缺的一部分。他们的角色从需求收集扩展到设计评审、原型验证和测试反馈的各个环节。通过持续的交流和迭代&#xff0c;业务专…

【FineReport的详细使用教程】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;今天主要和大家分享一下&#xff0c;BI报表中的FineRoport 的详细使用&#xff0c;以及它的优势&#xff01;&#xff01;&#xff01;希望对大家有所帮助。 &#x1f49e;&#x1f49e;代…

C# Winform布局控件的几种方式

在 C# WinForms 应用程序中&#xff0c;布局控件和布局管理器可以帮助开发者创建响应式的用户界面&#xff0c;即使在窗口大小改变时也能保持控件的正确位置和尺寸。 通常我们采用Panel和Dock&#xff0c;辅助Anchor实现类似如下的布局。 以下是几种常见的布局控件和方法&…

计算机网络通信

1、最原始的hub结构 2、局域网的交换机&#xff1a;mac和交换机端口路由表-数据链路层 mac地址 3、不同局域网之间进行通信&#xff0c;主要是路由器-网络层-ip 源ip到目标ip的不变化&#xff0c;但是mac地址在一直变化

Linux--信号量

线程系列&#xff1a; Linux–线程的认识(一) Linux–线程的分离、线程库的地址关系的理解、线程的简单封装&#xff08;二&#xff09; 线程的互斥&#xff1a;临界资源只能在同一时间被一个线程使用 生产消费模型 信号量 信号量&#xff08;Semaphore&#xff09;是在多线程…