JS设计模式之“神奇的魔术师” - 简单工厂模式

news2024/11/15 19:35:18

image.png

引言

在JavaScript开发中,我们经常需要创建和管理各种对象,而简单工厂模式就是一种最简单的用来创建对象的设计模式。

简单工厂模式通过一个工厂类来创建相似的对象,而无需直接使用具体类来实例化对象。这样可以将对象的创建过程与使用过程分离,提供了更好的灵活性和可维护性。

在本篇文章中,我将为您讲解以下内容:

  1. 什么是简单工厂模式?它的基本思想和原理是什么?

  2. 如何在JavaScript中使用简单工厂模式?

  3. 简单工厂模式的优点和缺点是什么?

  4. 真实场景下的案例分析和应用实践。

一. 什么是简单工厂模式

简单工厂模式(Simple Factory):又叫静态工厂方法,由一个工厂对象决定创建某一种产品对象类的实例,主要用来创建同一类对象。

JavaScript 简单工厂模式是一种编程设计模式,用于创建对象。它通过提供一个简单的工厂函数来封装对象的创建过程,以避免直接使用构造函数或复杂的创建逻辑。

fileOf7174.png

简单工厂模式的基本思想是,根据输入参数的不同,返回不同类的实例。这样可以隐藏对象的创建细节,并将 客户端 与具体的类解耦。

简单工厂模式在一些场景下非常有用,例如当需要根据条件动态创建对象或者创建对象过程比较复杂时。它可以简化客户端的代码,提高代码的可维护性和可扩展性。

二. 实现简单工厂模式的几种方式

简单工厂模式有几种实现方式,以下是常见的几种:

image.png

动物类工厂

模拟场景: 以动物类工厂AnimalFactory为例,下面将使用三种不同的方法来进行实践,使用AnimalFactory分别创建了 dogcat 两个动物对象,最后会分别调用了它们的 sound 方法。

1. 静态工厂方法:

这是最常见的实现方式,静态工厂方法是一种在类上定义的方法,用于创建和返回对象实例。使用静态工厂方法可以将对象的创建逻辑封装在类内部,使得客户端只需通过调用方法即可获取到所需的对象。

// 定义一个工厂类
class AnimalFactory {
  // 静态工厂方法,根据类型创建不同的动物对象
  static createAnimal(type) {
    if (type === 'dog') {
      return new Dog();
    } else if (type === 'cat') {
      return new Cat();
    } else {
      throw new Error('Invalid type: ' + type);
    }
  }
}

// 定义动物类
class Dog {
  sound() {
    console.log('Woof!');
  }
}

class Cat {
  sound() {
    console.log('Meow!');
  }
}

// 使用工厂方法创建对象
const dog = AnimalFactory.createAnimal('dog');
const cat = AnimalFactory.createAnimal('cat');

dog.sound(); // 输出: Woof!
cat.sound(); // 输出: Meow!

在上面的代码中,我们首先定义了一个工厂类 AnimalFactory,其中包含一个静态方法 createAnimal,根据传入的类型参数,创建并返回不同类型的动物对象。

接着,我们定义了 DogCat 两个具体的动物类,它们都实现了 sound 方法。

最后,我们使用工厂方法 AnimalFactory.createAnimal 分别创建了 dogcat 两个动物对象,并调用了它们的 sound 方法。

2. 实例化工厂对象:

将工厂函数定义为一个实例对象的方法,在创建工厂对象的时候传入构造函数,并通过调用实例方法来创建对象。

// 定义一个工厂类
class AnimalFactory {
  // 根据类型创建不同的动物对象
  createAnimal(type) {
    if (type === 'dog') {
      return new Dog();
    } else if (type === 'cat') {
      return new Cat();
    } else {
      throw new Error('Invalid type: ' + type);
    }
  }
}

// 定义动物类
class Dog {
  sound() {
    console.log('Woof!');
  }
}

class Cat {
  sound() {
    console.log('Meow!');
  }
}

// 实例化工厂对象
const factory = new AnimalFactory();

// 使用工厂对象创建对象
const dog = factory.createAnimal('dog');
const cat = factory.createAnimal('cat');

dog.sound(); // 输出: Woof!
cat.sound(); // 输出: Meow!

在上面的代码中,我们定义了一个 AnimalFactory 工厂类,其中包含一个 createAnimal 方法。与之前不同的是,这次是通过实例化工厂对象的方式来使用工厂方法。

接着,我们定义了 DogCat 两个具体的动物类,它们都实现了 sound 方法。

然后,我们实例化了一个 AnimalFactory 对象,并使用 factory.createAnimal 方法分别创建了 dogcat 两个动物对象,并调用了它们的 sound 方法。

使用实例化工厂对象的方式实现简单工厂模式,与使用静态工厂方法的实现相比,更加灵活,可以在工厂对象中保存状态,进行更复杂的对象创建逻辑。

3. 使用闭包封装工厂函数:

闭包是一种函数和其相关引用环境(词法环境)的组合。使用闭包可以实现封装和私有变量等特性。利用闭包将工厂函数封装起来,返回一个创建对象的函数,通过调用这个函数来创建对象。

// 封装工厂函数
const AnimalFactory = (function() {
  // 私有变量和方法
  const animals = {
    dog: Dog,
    cat: Cat
  };

  // 返回工厂函数
  return function(type) {
    if (typeof animals[type] !== 'function') {
      throw new Error('Invalid type: ' + type);
    }
    return new animals[type]();
  };
})();

// 定义动物类
class Dog {
  sound() {
    console.log('Woof!');
  }
}

class Cat {
  sound() {
    console.log('Meow!');
  }
}

// 使用闭包封装的工厂函数创建对象
const dog = AnimalFactory('dog');
const cat = AnimalFactory('cat');

dog.sound(); // 输出: Woof!
cat.sound(); // 输出: Meow!

在上面的代码中,我们使用闭包将工厂函数封装在一个立即执行函数表达式 (IIFE) 中。这样做的好处是可以创建一个私有的变量 animals 来存储不同类型动物的构造函数。通过这种方式,我们可以在工厂函数内部访问 animals 对象,并根据传入的类型来创建对应的对象。

然后,我们定义了 DogCat 两个具体的动物类,它们都实现了 sound 方法。

最后,我们使用封装在闭包中的工厂函数 AnimalFactory 创建了 dogcat 两个动物对象,并调用了它们的 sound 方法。

通过使用闭包封装工厂函数,我们可以将工厂函数的内部状态和逻辑隐藏起来,只暴露一个公共的接口。这样可以实现更好的封装和信息隐藏,避免对外暴露不必要的细节。

总结:以上三种方式都是常见的简单工厂模式的实现方式,每种方式都有各自的点和适用场景,它们在应用方面也有一些区别,可以根据具体需选择合适的方式来实现简单工厂模式。

三. 类与简单工厂模式

简单工厂模式是一种创建对象的设计模式,而类是面向对象编程的基本概念。它们之间有以下异同点:

1. 异同点:

  • 创建对象方式:简单工厂模式使用工厂函数来创建对象,根据输入参数的不同返回不同类的实例;而类则是通过定义构造函数和使用 new 关键字来创建对象。

  • 继承关系:简单工厂模式的工厂函数负责创建不同类的实例,这些类可以是没有继承关系的独立类;而类是通过继承实现类与类之间的层次关系。

  • 类型判断:使用简单工厂模式创建的对象可以通过参数类型进行判断;而类可以通过 of 运算符来判断对象的类型。

  • 对象的创建逻辑:简单工厂模式将对象的创建逻辑封装在工厂函数中,客户端只需调用工厂函数,而不关心具体的创建过程;而类的创建逻辑则是在构造函数中。

2. 案例分析:

image.png

模拟场景

假设我们需要创建不同类型的汽车对象,其中包括小轿车(sedan)和越野车(SUV)。使用简单工厂模式和类的方式可以如下实现:

使用类:

class Car {
  constructor(type) {
    this.type = type;
  }
}

class SedanCar extends Car {
  constructor() {
   super("sedan");
  }
}
class SUVCar extends Car {
 constructor() {
    super("SUV");
  }
}

var myCar = new SedanCar();
console.log(myCar.type); // 输出: "sedan"

var anotherCar = new SUVCar();
console.log(anotherCar.type); //: "SUV"

使用简单工厂模式:

function CarFactory() {

}

CarFactory.createCar = function(type) {
  if (type === "sedan") {
    return new SedanCar();
  } else if (type === "SUV") {
    return new SUVCar();
  } else {
    throw new Error("Invalid car type.");
  }
}

function SedanCar() {
  this.type = "sedan";
}

function SUVCar() {
  this.type = "SUV";
}

var myCar = CarFactory.createCar("sedan");
console.log(myCar.type); // 输出: "sedan"

var anotherCar = CarFactory.createCar("SUV");
console.log(anotherCar.type); // 输出: "SUV"

以上两种方式都能所需的汽车对象,其中简工厂模式将对象创建逻辑封装在 CarFactory 工厂函数中,类的方式则通过继承和构造函数来创建不同类型的汽车对象。

四. 简单工厂模式的优缺点

以上我们了解到简单工厂模式是一种创建对象的设计模式,它具有以下优点和缺点:

1. 优点:

  1. 封装了对象的创建逻辑,客户端只需通过工厂函数来创建对象,而不需要了解具体的创建过程,降低了客户端的复杂性和依赖性。

  2. 可以集中管理对象的创建逻辑,方便统一修改和维护。如果需要新增或修改对象的创建方式只需修改工厂函数中的代码即可,而不需要修改客户端的代码。

  3. 实现了对象创建解耦,客户端与工厂函数进行交互,不直接依赖具体的类,增加了灵活性和可扩展性。

2. 缺点:

  1. 违背了开闭原则,需要新增一种类型的对象时,必须修改工厂函数的代码,增加了厂函数的维护成本。

  2. 创建对象的逻辑集中工厂函数中,导致工厂函数的代码可能过于复杂不易维护和扩展

  3. 不符合单一职责原则,一个工厂函数负责创建多种类型的对象,当对象创建逻辑复杂时,工厂函数会变得臃肿。

结语

相信通过本文对简单工厂模式的学习,你一定对这个设计模式有了更深入的了解。

简单工厂模式是一种常用的创建型设计模式,在JavaScript中广泛应用于对象的创建和管理。它通过一个工厂类来将对象的创建过程与使用过程分离,提供了更好的灵活性和可维护性。

在使用简单工厂模式时,我们可以通过工厂类创建不同类型的对象,而无需直接使用具体类来实例化对象。这样可以避免在客户端代码中直接暴露具体类,提高了代码的封装性和可扩展性。

同时,简单工厂模式也有一些限制,例如:难以支持复杂的对象创建逻辑或创建过程可能会非常复杂等。简单工厂模式适合创建对象较简单,类型不频繁变化的场景。如果需要创建的对象较复杂,或者对象的类型经常变化,适合使用其他创建对象的设计模,如工厂方法模式或抽象工厂模式,我将会在后面的文章继续讲解。在实际应用中,我们需要根据具体的场景和需求,选择合适的设计模式。

希望通过本文的介绍,您能够对JavaScript简单工厂模式有了更清晰的认识,并能够在实际项目中灵活应用。

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

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

相关文章

Zabbix 配置win系统登录和钉钉告警

1、配置win监控项 win系统日志ID 4624是成功登录 4625是失败登录 登录成功日志: eventlog[Security,,"Success Audit",,^4624$,,skip] 登录失败日志: eventlog[Security,,"Success Audit",,^4625$,,skip] 要监控登录的日志&…

音视频开发之旅(90)-Vision Transformer论文解读与源码分析

目录 1.背景和问题 2.Vision Transformer(VIT)模型结构 3.Patch Embedding 4.实现效果 5.代码解析 6.资料 一、背景和问题 上一篇我们学习了Transformer的原理,主要介绍了在NLP领域上的应用,那么在CV(图像视频)领域该如何使用? 最直观…

在Diffusers中使用LoRA微调模型

在浏览稳定扩散模型共享网站(例如 CivitAI)时,你可能遇到过一些标记为“LoRA”的自定义模型。“LoRA”到底是什么—它与典型的模型检查点有何不同?LoRA 可以与Diffusers包一起使用吗?在本文中,我们将回答这…

计算机视觉基础 2. 滤波器

1. 简介 模糊滤波器是低通滤波器。它们从图像中去除高空间频率内容,只留下低频空间分量。结果是图像失去了细节,看起来很模糊。图像模糊在计算机图形学和计算机视觉中有许多应用。它可用于降低噪声(如图17.1所示),揭示…

代码时光机:Git基础速成

hello,家人们,今天咱们来介绍Git以及Git相关的操作,好啦,废话不多讲,开干. 1:Git初识 在介绍Git前,博主首先讲一个小故事. 我们学计算机的小伙伴们,在学校里头都有实验课,那么老师呢就会要求我们写实验报告并且要求我们交上去给老师检查.有一个学计算机的大学生,名字叫张三,然…

Datawhale X 李宏毅苹果书 AI夏令营-深度学习进阶task2:自适应学习率,分类

1.自适应学习率 临界点其实不一定是在训练一个网络的时候会遇到的最大的障碍。很多时候训练网络,损失不再下降,不是因为到了临界点,而是可能在山谷之间不停震荡。 以下为不同学习率对训练的影响,下图中左右平缓,上下陡…

C语言 | Leetcode C语言题解之第387题字符串中的第一个唯一字符

题目&#xff1a; 题解&#xff1a; struct hashTable {int key;int val;UT_hash_handle hh; };int firstUniqChar(char* s) {struct hashTable* position NULL;int que[26][2], left 0, right 0;int n strlen(s);for (int i 0; i < n; i) {int ikey s[i];struct has…

火语言RPA流程组件介绍--浏览选择文件夹

&#x1f6a9;【组件功能】&#xff1a;打开浏览文件夹选择对话框 配置预览 配置说明 对话框标题 支持T或# 打开浏览文件夹对话框时显示的标题。 默认打开文件夹 支持T或# 打开浏览文件夹对话框时&#xff0c;默认打开此文件夹。 取消后终止流程 “是”、“否”2种供选择…

一篇详细介绍常用第三方库的教程

作者&#xff1a;郭震 我们之前介绍过如何安装Python的各种常用第三方库.这些库为程序员提供了许多功能,能够大大简化我们的开发工作.本文将为你介绍一些最常用的第三方库,帮助你更好地理解它们的用途及基本概念. 1. NumPy NumPy是一个强大的科学计算库.它提供了多维数组对象以…

09.定时器02

#include "reg52.h"sbit led P3^6;void delay10ms() { //1. 配置定时器0工作模式位16位计时TMOD 0x01;//2. 给初值&#xff0c;定一个10ms出来TL00x00;TH00xDC;//3. 开始计时TR0 1;TF0 0; } void main() {int cnt 0;led 1;while(1){if(TF0 1)//当爆表的时候&a…

Git之2.9版本重要特性及用法实例(五十八)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者. 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列…

非关系型数据库 Redis 的安装与配置

文章目录 一 . CentOS 7 安装 Redis【版本选择说明】一 . 安装 Redis二 . 配置 Redis2.1 针对可执行程序设置符号链接2.2 针对配置文件设置符号链接2.3 修改配置文件2.3.1 设置 IP 地址2.3.2 关闭保护模式2.3.3 启动守护进程2.3.4 设置工作目录2.3.5 设置日志目录 三 . 启动 Re…

Apache SeaTunnel Zeta 引擎源码解析(一)Server端的初始化

引入 本系列文章是基于 Apache SeaTunnel 2.3.6版本&#xff0c;围绕Zeta引擎给大家介绍其任务是如何从提交到运行的全流程&#xff0c;希望通过这篇文档&#xff0c;对刚刚上手SeaTunnel的朋友提供一些帮助。 我们整体的文章将会分成三篇&#xff0c;从以下方向给大家介绍&am…

掌握数据利器:AWS Glue与数据基盘概览

引言 随着数字化进程的不断推进&#xff0c;企业现在能够积累并分析海量且多样化的数据。这一优势使得许多企业开始采用数据驱动型经营&#xff08;即基于数据的经营策略&#xff09;。通过基于数据的客观判断&#xff0c;企业及其管理者可以获得诸多好处。 然而&#xff0c;…

DeepMind 机器人学习打乒乓球,朝着「专业运动员水平的速度和性能」发展

这几天全球各界最火热的话题非奥运会莫属&#xff0c;而其中乒乓球比赛更是引起了互联网的讨论热潮&#xff0c;无论是欢呼也好、争议也罢&#xff0c;在现实世界人类的乒乓球大赛风生水起的同时&#xff0c;AI已经偷偷在乒乓球上“出师”了—— ——DeepMind近日发布一项新工作…

机器学习 第7章 贝叶斯分类器

目录 7.1 贝叶斯决策论7.2 极大似然估计7.3 朴素贝叶斯分类器7.4 半朴素贝叶斯分类器7.5 贝叶斯网7.5.1 结构7.5.2 学习7.5.3 推断 7.6 EM算法 7.1 贝叶斯决策论 对分类任务来说&#xff0c;在所有相关概率都己知的理想情形下&#xff0c;贝叶斯决策论考虑如何基于这些概率和误…

如何删除浏览器每次登录自动保存的密码,以防自动登录泄露自己的隐私

今天小编以 Microsoft edge 浏览器为例&#xff0c;如何在自己离职或毕业以后留给他人的电脑是干净的&#xff0c;不会在任何网页登录时显示已保存的密码&#xff0c;让他人自动登录。 ①在电脑上打开 Microsoft edge 浏览器后&#xff0c;点击“设置” ②进入设置界面后&…

基于SSM的咖啡馆管理系统

基于SSM的咖啡馆管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatisJSP工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 前台界面 后台界面 摘要 在当前这个信息爆炸的时代&#xff0c;众多行业正经历着…

Python酷库之旅-第三方库Pandas(114)

目录 一、用法精讲 501、pandas.DataFrame.mode方法 501-1、语法 501-2、参数 501-3、功能 501-4、返回值 501-5、说明 501-6、用法 501-6-1、数据准备 501-6-2、代码示例 501-6-3、结果输出 502、pandas.DataFrame.pct_change方法 502-1、语法 502-2、参数 502…

[知识分享]华为铁三角工作法

在通信技术领域&#xff0c;尤其是无线通信和物联网领域&#xff0c;“华为铁三角”是华为公司内部的一种销售、交付和服务一体化的运作模式。这种模式强调的是以客户为中心&#xff0c;通过市场、销售、交付和服务三个关键环节的紧密协作&#xff0c;快速响应客户需求&#xf…