当前位置: 首页 > news >正文

JS设计模式之“名片设计师” - 工厂方法模式

image.png

image.png

前言

上篇文章我们了解到什么是简单工厂模式,请参考上篇文章:JS设计模式之 “神奇的魔术师” - 简单工厂模式,不过这是工厂中最简单的一种,本篇文章我们将同大家一起认识一种更复杂的工厂模式,它将给我们提供复杂的对象创建场景,以模块化的思想实现我们复杂的需求。就像给我们设计不同的名片一样,我们暂且亲切的称呼它为“名片设计师”。

一. 什么是工厂方法模式

概念

工厂方法模式Factory Method Pattern)是一种创建型设计模式,在软件开发中被广泛应用。它提供了一种将对象的创建过程封装起来的方式,使得代码可扩展性更好、更灵活。

工厂方法模式的主要思想是定义一个用于创建对象的接口,但将具体的对象创建延迟到子类中去实现。这样,客户端程序使用工厂方法来创建对象,而不需要知道具体的实现细节,从而实现了解耦

fileOf7174.png

工厂方法模式类图

使用步骤

JavaScript 中,可以使用工厂方法模式实现对象的创建和管理,具体的实现方式如下:

首先,定义一个基础工厂类,作为对象创建的接口,其中包含一个用于创建对象的方法(通常称为工厂方法)。

class Factory {createObject() {// 子类需要实现该方法来创建具体对象}
}

然后,根据具体的需求,创建子类继承基础工厂类,并实现工厂方法来创建具体的对象。

class ConcreteFactory extends Factory {createObject() {return new ConcreteObject();}
}

最后,通过客户端代码来使用工厂方法创建对象。

const factory = new ConcreteFactory();
const object = factory.createObject();

使用工厂方法模式的好处是,当需要新增一种对象时,只需要创建一个新的子类并实现工厂方法即可,而不需要修改客户端代码。这样,能够降低代码的耦合度,提高代码的可维护性可扩展性

工厂方法模式是一种简单而有效的对象创建方式,适用于需要创建多个具有相同行为的对象的场景,能够提供一种灵活的对象创建和管理机制。

二. 安全模式创建的工厂类

介绍

安全模式创建的工厂类Safe Factory Pattern)是一种在JavaScript中实现工厂方法模式的方式,它可以确保只能通过工厂类的方法来创建对象,而不能直接实例化工厂类。

通过使用安全模式创建工厂类,可以确保工厂类的使用符合预期,同时也增强了代码的安全性和可靠性。以下是一个简单示例:

function Factory() {if (!(this instanceof Factory)) {return new Factory();}this.createObject = function() {// 创建对象的逻辑};
}

在上述示例中,我们使用了构造函数Factory)来实现工厂类,并通过判断this对象是否是工厂类的实例来确保只能通过构造函数来创建工厂类的实例。这样,在使用时如果忘记使用new关键字来实例化工厂类,则会自动进行实例化,避免了直接实例化工厂类导致的问题。

通过使用安全模式创建的工厂类,可以实现更严格的对象创建和管理机制,同时保证了代码的安全性和一致性。在实际应用中,可以根据需求对工厂类进行扩展和定制,以满足具体的业务需求。

优点

由此可见,安全模式创建的工厂类具有以下优点

1. 隐藏实例化细节: 安全模式的工厂类只能通过工厂方法来创建对象,而不允许直接实例化或继承该工厂类。这样可以隐藏具体对象的实例化细节,使得客户端无法直接访问和创建对象,只能通过工厂方法来获取实例。

2. 防止子类破坏对象的创建逻辑: 由于安全模式的工厂类不能被继承,子类无法改变工厂方法中的创建逻辑。这确保了对象的创建过程不会被子类随意修改,防止了在创建过程中可能出现的错误或安全隐患。

3. 提供一致的接口: 通过工厂方法来统一创建对象,工厂类可以根据不同的参数或条件返回不同类型的对象,但对外提供的接口是一致的。这样可以简化客户端的使用,客户端不需要知道具体的创建过程,只需要调用工厂方法并传入相应的即可获得所需对象。

案例场景:日志工厂

下面以一个Logger工厂类的示例来说明安全模式创建工厂类的优点:

public abstract class Logger {public abstract void log(String message);
}public class FileLogger extends Logger {public void log(String message) {// 将日志信息写入文件}
}public class DatabaseLogger extends Logger {public void log(String message) {// 将日志信息写入数据库}
}public class LoggerFactory {private LoggerFactory() {}public static Logger createLogger type) {if (type.equals("file")) {return new FileLogger();} else if (type.equals("database")) {return new DatabaseLogger();} else {throw new IllegalArgumentException("Invalid logger type.");}}
}

在上述示例中,Logger是一个抽象类,具体的日志记录逻辑由FileLoggerDatabaseLogger来实现。LoggerFactory是一个安全模式创建的工厂类,通过工厂方法createLogger来创建Logger的实例。客户端只需调用LoggerFactorycreateLogger方法,并传入相应的参数(如filedatabase)即可获取对应的Logger实例。客户端无法直接实例化Logger类或LoggerFactory类,以保对象的创建逻辑被固定并且隐藏了具体实例化细节。这样的设计使得客户端使用起来更加简单方便,并且保护了对象创建过程的安全性和稳定性。

三. 简单工厂模式与工厂方法模式之间的对比

fileOf7174.png

披萨工厂

案例场景:披萨店点餐

当你在一个披萨店点餐时,你可以通过简单工厂模式或工厂方法模式来创建不同类型的披萨。这里有两个例子来说明它们之间的区别:

1. 简单工厂模式示例:

考虑一个披萨店,它提供不同类型的披萨,如奶酪披萨(Cheese Pizza)、蔬菜披萨(Vegetable Pizza)和海鲜披萨(Seafood Pizza)等。使用简单工厂模式,我们可以创建一个披萨工厂类来处理披萨的实例化逻辑:

public class PizzaFactory {public static Pizza createPizza(String type) {if (type.equals("cheese")) {return new CheesePizza();} else if (type.equals("vegetable")) {return new VegetablePizza();} else if (type.equals("seafood")) {return new SeafoodPizza();} else {throw new IllegalArgumentException("Invalid pizza type.");}}
}public abstract class Pizza {// 披萨的公共方法和属性
}public class CheesePizza extends Pizza {// 奶酪披萨特有的方法和属性
}// 其他类型的披萨类类似,如VegetablePizza和SeafoodPizza

使用简单工厂模式,我们只需要通过披萨工厂类(PizzaFactory)来创建不同类型的披萨对象,而不需要直接实例化特定类型的披萨。

2. 工厂方法模式示例:

假设我们的披萨店进一步发展,对于不同类型的披萨,现在要创建不同的披萨店来处理它们的制作。这里为每个披萨类型创建一个具体的披萨店类,用工厂方法模式实现:

public abstract class PizzaStore {public abstract Pizza createPizza();public void orderPizza() {Pizza pizza = createPizza();// 其他制作披萨的逻辑}
}public class CheesePizzaStore extends PizzaStore {public Pizza createPizza() {return new CheesePizza();}
}// 其他类型的披萨店类类似,如VegetablePizzaStore和SeafoodPizzaStore

在工厂方法模式中,我们定义了一个抽象的PizzaStore类,并在每个具体的店类(如CheesePizzaStore)中实现了创建具体披萨对象的方法。每个具体的店类负责创建特定的披萨类型,使得披萨的创建逻辑分散到不同的类中。

通过上述两个示例可以看出,简单工厂模式通过一个工厂类集中处理对象的创建逻辑,而工厂方法模式将对象的创建推迟到具体的子类中实现,从而使得不同的产品创建逻辑能够被更加灵活地扩展和修改。

由此可见,整体区别如下:

工厂方法模式Factory Method Pattern)和简单工厂模式Simple Factory Pattern)是两种常见的工厂模式,它们之间有以下区别:

1. 设计理念:

  • 简单工厂模式的主要思想是通过一个工厂类来创建不同类型的对象,将对象的创建逻辑集中在一个地方。工厂类根据传入的参数或条件来决定创建哪种对象。

  • 工厂方法模式的主要思想是将对象的创建延迟到子类中实现。定义一个抽象的工厂类,该类中声明一个工厂方法,由子类来实现该工厂方法来创建具体的对象。

2. 参与角色:

  • 简单工厂模式通常只涉及一个工厂类(Simple Factory)和多个产品类(Product)。

  • 工厂方法模式涉及一个抽象工厂类(Abstract Factory)、多个具体工厂类(Concrete Factory)和对应的产品类(Product)。

3. 可扩展性:

  • 简单工厂模式的可扩展性相对较差,当需要新增一种产品时,需要修改工厂类的代码来增加对新产品的支持。

  • 工厂方法模式的可扩展性较好,通过添加一个新的具体工厂类和对应的产品类,即可实现对新产品的支持,不需要修改抽象工厂类或其他已有类。

4. 对象创建的灵活性:

  • 简单工厂模式在工厂类中集中了对象的创建逻辑,可能会导致工厂类变得较为庞大,一旦需要新增或修改某个产品的创建逻辑,就需要修改工厂类。

  • 工厂方法模式将对象的创建委托给具体的工厂类,每个工厂类只负责创建一个具体的产品,使得代码更加模块化和灵活,容易扩展和维护。

总结

简单工厂模式适用于简单的对象创建场景,可以通过一个工厂类来集中对象的创建逻辑;而工厂方法模式适用于复杂的对象创建场景,需要根据具体的产品类型来创建相应的对象,通过子类来实现对象的创建逻辑。选择使用哪种模式取决于具体的需求和设计的复杂性。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 达梦数据库事务管理
  • java中使用MongoTemplate入门学习
  • 国内可以免费使用的gpt网站【九月持续更新】
  • InstantX团队新作!基于端到端训练的风格转换模型CSGO
  • 鸿蒙(API 12 Beta6版)图形【NativeImage开发指导 (C/C++)】方舟2D图形服务
  • 深度探索Unity与C#:编织游戏世界的奇幻篇章
  • uniapp组件中的emit声明触发事件
  • shell脚本编程(函数)
  • 网络编程--python
  • Vue3 中的响应式系统:深入理解 Proxy API
  • 第四十篇-TeslaP40+Ollama+Ollama-WebUI(自编译)
  • flume 使用 exec 采集容器日志,转储磁盘
  • 游戏翻译中西班牙语的特点
  • PHP一站式班级解决方案班级管家系统小程序源码
  • 【主机入侵检测】Wazuh解码器之JSON解码器
  • 分享的文章《人生如棋》
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • flask接收请求并推入栈
  • Iterator 和 for...of 循环
  • java概述
  • jQuery(一)
  • JS数组方法汇总
  • 大数据与云计算学习:数据分析(二)
  • 前端技术周刊 2019-02-11 Serverless
  • 悄悄地说一个bug
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 微服务入门【系列视频课程】
  • 微信小程序开发问题汇总
  • 译自由幺半群
  • 【云吞铺子】性能抖动剖析(二)
  • 翻译 | The Principles of OOD 面向对象设计原则
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • ###STL(标准模板库)
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (13):Silverlight 2 数据与通信之WebRequest
  • (173)FPGA约束:单周期时序分析或默认时序分析
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (Qt) 默认QtWidget应用包含什么?
  • (办公)springboot配置aop处理请求.
  • (多级缓存)缓存同步
  • (分布式缓存)Redis分片集群
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (接口自动化)Python3操作MySQL数据库
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (十三)Maven插件解析运行机制
  • (四)鸿鹄云架构一服务注册中心
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • (转)原始图像数据和PDF中的图像数据
  • *** 2003