js构造函数之工厂模式(学习笔记1)

目录

一、简单工厂

1、存储一个用户信息

2、存储N个用户信息

3、存储N个用户信息+不同年龄用户有不同美食的搭配方案【简单工厂模式】

二、抽象工厂模式

1、抽象工厂(AbstractFactory)

2、具体工厂(ConcreteFactory)

3、生产新款手机

4、总结


本文是小编阅读《JavaScript 设计模式核心原理与应用实践》这本书,记录的学习笔记,更多详细知识可以直接阅读原文

JavaScript 设计模式核心原理与应用实践——掘金小册icon-default.png?t=N7T8https://juejin.cn/book/6844733790204461070/section/6844733790246404109首要任务:认识哪些是变与不变


一、简单工厂

通过实现用户需求举例

1、存储一个用户信息

// 原始对象
const obj = {
  id:1,
  name:'sxx',
  age:19,
  sex:1
}
console.log(obj);

2、存储N个用户信息

// 简单构造器
class User{
  constructor(id,name,age,sex){
    this.id = id
    this.name = name
    this.age = age
    this.sex = sex
  }
}
// 调用简单构造器
const me = new User(1,'sxx',19,1);
const you = new User(2,'张三',66,0);
console.log(me,you);

在创建一个user过程中,谁变了,谁不变?

很明显,变的是每个user的姓名、年龄这些值,这是用户的个性,不变的是每个员工都具备姓名、年龄、工种这些属性,这是用户的共性

3、存储N个用户信息+不同年龄用户有不同美食的搭配方案【简单工厂模式】

(1)笨方法

// 一个一个构建构造器【笨方法】
class Young{
  constructor(id,name,sex){
    this.id = id
    this.name = name
    this.age = 19
    this.sex = sex
    this.food = ['汉堡','炸鸡','可乐']
  }
}
class Old{
  constructor(id,name,sex){
    this.id = id
    this.name = name
    this.age = 99
    this.sex = sex
    this.food = ['稀饭','青菜','荔枝肉']
  }
}
function Factory(id,name,age,sex){
  switch(age){
    case 19:
      return new Young(id,name,sex)
    case 99:
      return new Old(id,name,sex)
  }
}
const me = Factory(1,'sxx',19,1)
const you = Factory(2,'张三',99,0)
console.log(me,you);

(2)灵活方法

// 观察变与不变【灵活方法】
class User{
  constructor(id,name,age,sex,food){
    this.id = id
    this.name = name
    this.age = age
    this.sex = sex
    this.food = food
  }
}
function Factory(id,name,age,sex){
  let food
  switch(age){
    case 3:
      food = ['奶粉','米糊']
      break
    case 19:
      food = ['汉堡','炸鸡','可乐']
      break
    case 99:
      food = ['稀饭','青菜','荔枝肉']
      break
  }
  return new User(id,name,age,sex,food)
}
console.log(Factory(1,'baby',3,0));
console.log(Factory(2,'sxx',19,1));
console.log(Factory(3,'张三',99,0));


新的需求:

①推出普通、豪华、至尊等套餐,不同年龄用户能够自主选择套餐

②拓展功能:供服务员、厨师、老板等使用

以上需求,每一次都要回去修改 Factory 的函数体,Factory会变得异常庞大——没有遵守开放封闭原则

开放封闭原则:对拓展开放,对修改封闭。软件实体(类、模块、函数)可以扩展,但是不可修改


二、抽象工厂模式

举例:制造智能手机
已知
        ①智能手机的基本组成操作系统和硬件
        ②二者条件兼顾才能实现量产
        ③二者不同的厂商并不知道下一个生产线具体要生产的设计
解决措施
        写一个抽象类,约定某手机的基本组成

1、抽象工厂(AbstractFactory)

class MobilePhoneFactory {
    // 提供操作系统的接口
    createOS(){
        throw new Error("抽象工厂方法不允许直接调用,你需要将我重写!");
    }
    // 提供硬件的接口
    createHardWare(){
        throw new Error("抽象工厂方法不允许直接调用,你需要将我重写!");
    }
}

(1)以上类,除了约定手机流水线的通用能力之外,啥也不干。如果让它干点啥,比如 new 一个 MobilePhoneFactory 实例,并尝试调用它的实例方法,它将报错

(2)在抽象工厂模式中,以上类就是食物链顶端最大的Boss

2、具体工厂(ConcreteFactory)

当明确了生产方案:抽象工厂不工作,具体工厂来工作
举例:一个专门生产 Android 系统 + 高通硬件的手机(FakeStar)的生产线

(1)定制一个具体工厂

// 具体工厂继承自抽象工厂
class FakeStarFactory extends MobilePhoneFactory {
    createOS() {
        // 调用AndroidOS()构造函数,提供安卓系统实例
        return new AndroidOS()
    }
    createHardWare() {
        // 调用QualcommHardWare()构造函数,提供高通硬件实例
        return new QualcommHardWare()
    }
}

①两个构造函数:AndroidOS 和 QualcommHardWare,分别用于生成具体的操作系统和硬件实例像这种被用于 new 出具体对象的类,叫做具体产品类(ConcreteProduct)

具体产品类往往不会孤立存在,不同的具体产品类往往有着共同的功能,比如安卓系统类和苹果系统类,它们都是操作系统,都有着可以操控手机硬件系统这样一个最基本的功能

③因此我们可以用一个抽象产品(AbstractProduct)类来声明这一类产品应该具有的基本功能

(2)抽象产品类

// 定义操作系统这类产品的抽象产品类
class OS {
    controlHardWare() {
        throw new Error('抽象产品方法不允许直接调用,你需要将我重写!');
    }
}

// 定义具体操作系统的具体产品类
class AndroidOS extends OS {
    controlHardWare() {
        console.log('我会用安卓的方式去操作硬件')
    }
}

class AppleOS extends OS {
    controlHardWare() {
        console.log('我会用🍎的方式去操作硬件')
    }
}
...

(3)硬件类产品

// 定义手机硬件这类产品的抽象产品类
class HardWare {
    // 手机硬件的共性方法,这里提取了“根据命令运转”这个共性
    operateByOrder() {
        throw new Error('抽象产品方法不允许直接调用,你需要将我重写!');
    }
}

// 定义具体硬件的具体产品类
class QualcommHardWare extends HardWare {
    operateByOrder() {
        console.log('我会用高通的方式去运转')
    }
}

class MiWare extends HardWare {
    operateByOrder() {
        console.log('我会用小米的方式去运转')
    }
}
...

(4)生产一台FakeStar手机

// 这是我的手机
const myPhone = new FakeStarFactory()
// 让它拥有操作系统
const myOS = myPhone.createOS()
// 让它拥有硬件
const myHardWare = myPhone.createHardWare()
// 启动操作系统(输出‘我会用安卓的方式去操作硬件’)
myOS.controlHardWare()
// 唤醒硬件(输出‘我会用高通的方式去运转’)
myHardWare.operateByOrder()

3、生产新款手机

此时我们不需要对抽象工厂MobilePhoneFactory做任何修改,只需要拓展它的种类
这样对原有的系统不会造成任何潜在影响,即“对拓展开放,对修改封闭”

class newStarFactory extends MobilePhoneFactory {
    createOS() {
        // 操作系统实现代码
    }
    createHardWare() {
        // 硬件实现代码
    }
}

4、总结

(1)抽象工厂和简单工厂有哪些异同?

①共同点:尝试去分离一个系统中变与不变的部分
②不同点:场景的复杂度

简单工厂:处理容易抽离的类

    逻辑本身比较简单,故而不苛求代码可扩展性。

抽象工厂:处理非常棘手、繁杂的类

    这些类中不仅能划分出门派,还能划分出等级,同时存在着千变万化的扩展可能性

    这使得我们必须对共性作更特别的处理、使用抽象类去降低扩展的成本,同时需要对类的性质作划分

(2)四个关键角色

  • 抽象工厂(抽象类,不能被用于生成具体实例):  用于声明最终目标产品的共性。在一个系统里,抽象工厂可以有多个(大家可以想象我们的手机厂后来被一个更大的厂收购了,这个厂里除了手机抽象类,还有平板、游戏机抽象类等等),每一个抽象工厂对应的这一类的产品,被称为“产品族
  • 具体工厂(用于生成产品族里的一个具体的产品):  继承自抽象工厂、实现了抽象工厂里声明的那些方法,用于创建具体的产品的类
  • 抽象产品(抽象类,不能被用于生成具体实例):  上面我们看到,具体工厂里实现的接口,会依赖一些类,这些类对应到各种各样的具体的细粒度产品(比如操作系统、硬件等),这些具体产品类的共性各自抽离,便对应到了各自的抽象产品类
  • 具体产品(用于生成产品族里的一个具体的产品所依赖的更细粒度的产品):  比如我们上文中具体的一种操作系统、或具体的一种硬件等

(3)学习注意点

①学会用 ES6 模拟 JAVA 中的抽象类

②了解抽象工厂模式中四个角色的定位与作用

③对“开放封闭原则”形成自己的理解,知道它好在哪,知道执行它的必要性

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

V10服务器安装virt-manage

kvm是什么 KVM(Kernel-based Virtual Machine, 即内核级虚拟机) 是一个开源的系统虚拟化模块。它使用Linux自身的调度器进行管理,所以相对于Xen,其核心源码很少。目前KVM已成为学术界的主流VMM之一,它包含一个为处理器提供底层虚拟化 可加载…

服务器数据恢复—服务器raid5离线磁盘上线同步失败的数据恢复案例

服务器数据恢复环境&故障: 某品牌DL380服务器中有一组由三块SAS硬盘组建的RAID5阵列。数据库存放在D分区,数据库备份存放在E分区。 服务器上有一块硬盘的状态灯显示红色,D分区无法识别,E分区可识别,但是拷贝文件报…

MyBatis 操作数据库(⼊⻔)

前言 通过本篇博客,我们将学到以下内容 1.使⽤MyBatis完成简单的增删改查操作,参数传递 2.掌握MyBatis的两种写法: 注解和 XML⽅式 3.掌握 MyBatis 相关的⽇志配置 什么是 MyBatis? MyBatis是⼀款优秀的 持久层 框架,⽤于简化JDBC(关于 JD…

推荐5款堪称神器的免费软件

​ 今天再次推荐5个良心好用的Windows神级软件,每一个都是完全免费,堪称神器,让你打开新世界的大门。 1.文件复制——SuperCopy ​ SuperCopy 是一款 Chrome 浏览器的扩展,可以帮助您解除网站上禁止复制、右键、全选、粘贴等限制…

Linux Docker图形化工具Portainer如何进行远程访问?

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 Portainer 是一个轻量级的容器管理工具,可以通过 Web 界面对 Docker 容器进行管理和监控。它提供了可…

easyExcle单元格合并

自定义单元格合并策略: /*** 自定义单元格合并策略** create: 2023-11-15 13:41**/ Data NoArgsConstructor AllArgsConstructor Slf4j public class EasyExcelCustomMergeStrategy implements RowWriteHandler {/*** 总数*/private Integer totalNum;//合并行计数…

填充每个节点的下一个右侧节点指针

题目链接 填充每个节点的下一个右侧节点指针 题目描述 注意点 给定一个 完美二叉树 解答思路 广度优先遍历一层层的遍历二叉树,将每一层节点的next指针都指向右侧节点 代码 class Solution {public Node connect(Node root) {if (root null) {return null;}…

[nlp] 损失缩放(Loss Scaling)loss sacle

在深度学习中,由于浮点数的精度限制,当模型参数非常大时,会出现数值溢出的问题,这可能会导致模型训练不稳定。为了解决这个问题,损失缩放(Loss Scaling)技术被引入,它通过缩放损失值来解决这个问题。 在深度学习中,损失缩放技术通常是通过将梯度进行缩放来实现的。具…

【ES6标准入门】JavaScript中的模块Module语法的使用细节:export命令和imprt命令详细使用,超级详细!!!

😁 作者简介:一名大四的学生,致力学习前端开发技术 ⭐️个人主页:夜宵饽饽的主页 ❔ 系列专栏:JavaScript进阶指南 👐学习格言:成功不是终点,失败也并非末日,最重要的是继…

Google codelab WebGPU入门教程源码<5> - 使用Storage类型对象给着色器传数据(源码)

对应的教程文章: https://codelabs.developers.google.com/your-first-webgpu-app?hlzh-cn#5 对应的源码执行效果: 对应的教程源码: 此处源码和教程本身提供的部分代码可能存在一点差异。运行的时候,点击画面可以切换效果。 class Color4 {r: number;g: numb…

Java面向对象(高级)-- static关键字的使用

文章目录 一、static关键字(1)类属性、类方法的设计思想(2) static关键字的说明(3)static修饰属性1. 复习变量的分类2. 静态变量2.1 语法格式2.2 静态变量的特点2.3 举例2.3.1 举例12.3.2 举例22.3.3 举例3…

linux套接字-Socket

1.概念 局域网和广域网 局域网:局域网将一定区域内的各种计算机、外部设备和数据库连接起来形成计算机通信的私有网络。广域网:又称广域网、外网、公网。是连接不同地区局域网或城域网计算机通信的远程公共网络。IPInternet Protocol)&#…

无需云盘,不限流量实现Zotero跨平台同步:内网穿透+私有WebDAV服务器

🔥博客主页: 小羊失眠啦. 🎥系列专栏:《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞👍收藏⭐评论✍️ 无需云盘,不限流量实现Zotero跨平台同步:内网穿透私有WebDAV服务器 文章目…

系列八、堆(Heap)

一、概述 一个JVM实例只存在一个堆内存,堆内存的大小是可以手动调节的。类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行,堆内存分为三个部分,即…

高压开关柜实现无线测温监控关键点在哪里?

近年来,电力系统已发生多起因设备过热而发生火灾和大面积停电事故。据统计分析,我国每年发生的电力事故,有40%是由高压电气设备过热所致;而在采用高压开关柜和电力电缆的供电系统中,有70%以上的…

36、Flink 的 Formats 之Parquet 和 Orc Format

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

教育案例分享 | 安全狗云安全体系为高校提升立体化纵深防御能力

一、客户情况 某高校有服务器500台,对外站点200个,核心交换流量20G。 二、客户痛点 校园网系统分类较多,并且每类网站中安全级重要程度又各不相同,同时有多个网络出口(如:教育网、电信网、移动网等),二级学…

你不懂API接口是什么?怎么和程序员做朋友

说到开发平台就一定离不开接口,作为PM,我们不需要对接口了解的特别细。只需要知道接口是什么,有什么用,有哪些要素就行。 1. 接口是什么 (1) 硬件接口 生活中我们经常会接触接口,最常见的就是HDMI接口和USB接口&…

软件测试/测试开发丨人工智能产品质量保障:挑战与创新

点此领取人工智能课程 人工智能产品的质量保障与测试是当前软件开发领域最具挑战性的任务之一。随着人工智能技术的迅猛发展,产品日益复杂,传统测试方法逐渐显得力不从心。在这个背景下,我们需要创新性地思考并采用新的策略,以确…

使用 Java 枚举和自定义数据类型

介绍 在 Java 编程领域,理解并有效利用枚举和自定义数据类型对于编写健壮、可维护且高效的代码至关重要。这篇文章旨在深入研究 Java 枚举和自定义数据类型的概念,提供见解和示例,以增强您的编码技能和知识。 理解 Java 中的枚举 枚举是枚…