JavaScript设计模式(二)——简单工厂模式、抽象工厂模式、建造者模式

news2024/12/23 23:42:38

个人简介

👀个人主页: 前端杂货铺
🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒Three.js 🍖JS版算法
🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧

文章目录

    • ✨✨前言
    • 一、简单工厂模式
    • 二、抽象工厂模式
    • 三、建造者模式
    • 🎉🎉本篇小结


✨✨前言

大家好,这里是前端杂货铺。

上一节,我们学习了构造器模式、原型模式和类模式,并认识到了类模式 = 构造器模式 + 原型模式。这一节,我们学习简单工厂模式、抽象工厂模式和建造者模式,认识它们的用途以及区别…

一、简单工厂模式

由一个简答工厂对象决定创建某一种产品对象类的实例。主要用来创建某一类对象。

举个栗子:对于后台管理系统,一般都会有 侧边栏权限分配 的问题。比如说:

  • superadmin 的权限包括 “home”, “user-manager”, “right-manage”, “news-manage”。
  • admin 的权限包括 “home”, “user-manage”, “news-manage”
  • editor 的权限包括 “home”, “news-manage”

那么当某类人员登录进来,侧边栏就需要显示该人员权限范围内的功能,这时候就可以使用简单工厂模式。

class User {
    constructor(role, pages) {
        this.role = role;
        this.pages = pages;
    }
    static UserFactory(role) {
        switch (role) {
            case "superadmin":
                console.log(new User("superadmin", ["home", "user-manager", "right-manage", "news-manage"]));
                break;
            case "admin":
                console.log(new User("admin", ["home", "user-manage", "news-manage"]));
                break;
            case "editor":
                console.log(new User("editor", ["home", "news-manage"]));
                break;
            default:
                throw new Error("参数错误");
        }
    }
}

let user = User.UserFactory("superadmin");
console.log(user);

在这里插入图片描述

简单工厂模式的优点:我们只需要一个正确的参数,就可以获取到我们所需要的对象,无需知道其创建的具体细节。

简单工厂模式的缺点:当我们的对象较多时,函数会非常庞大,难以维护。

so,简单工厂模式只适用于 创建的对象数量较少,对象的创建逻辑不复杂时使用。


二、抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是 围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

抽象工厂模式并不直接生成实例,而是用于对产品类簇的创建。

我们先创建一个 User 类(超级工厂),里面有两个方法,welcome() 方法用于欢迎某一类人,dataShow() 方法用于打印某一类人(子类重写的方式)。

之后我们创建三个子类 SuperAdmin、Admin、Editor(其他工厂),均继承自 User,它们继承父类的 name 和 welcome() 方法,重写父类的 dataShow() 方法。

最后我们创建 getAbstractUserFactory() 函数,传 role 参数,通过 switch - case 返回相应的类进行权限分配。

这样我们就对原本庞大的函数进行了解耦,更加容易理解和维护。

class User {
    constructor(name, role, pages) {
        this.name = name;
        this.role = role;
        this.pages = pages;
    }

    welcome() {
        console.log("欢迎回来", this.name);
    }

    dataShow() {
        throw new Error("抽象方法需要被实现");
    }
}

class SuperAdmin extends User {
    constructor(name) {
        super(name, "superadmin", ["home", "user-manager", "right-manage", "news-manage"]);
    }

    dataShow() {
        console.log("superadmin-datashow");
    }
}

class Admin extends User {
    constructor(name) {
        super(name, "admin", ["home", "user-manage", "news-manage"]);
    }

    dataShow() {
        console.log("admin-datashow");
    }
}

class Editor extends User {
    constructor(name) {
        super(name, "editor", ["home", "news-manage"]);
    }

    dataShow() {
        console.log("editor-datashow");
    }
}

function getAbstractUserFactory(role) {
    switch(role) {
        case "superadmin": 
            return SuperAdmin;
        case "admin":
            return Admin;
        case "editor":
            return Editor;
        default: 
            throw new Error("参数错误");
    }
}

let UserClass = getAbstractUserFactory("admin");
let user = new UserClass("前端杂货铺");
user.dataShow();
user.welcome();

在这里插入图片描述


三、建造者模式

建造者模式属于创建型模式的一种,提供一种创建复杂对象的方式它将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

建造者模式是 一步一步的 创建一个复杂的对象,它 允许用户只通过指定复杂的对象的类型和内容就可以构建它们,用户不需要指定内部的具体构造细节。

我们模拟一下场景。如下图,我们把 分类菜单 看做 NavBar,把 热门推荐列表的内容 看做 List。当页面加载的时候,会首先初始化(即 init) NavBar 和 List,之后异步获取相应数据(即 getData),最后进行页面渲染(即 render)。

在这里插入图片描述

我们构建了两个同性质的类 Navbar 和 List(干的事是一样的,都是 init => getData => render),之后创建了建造者类 Creator,并添加了一个异步的 startBuild 方法,它接收一个参数 builder (即 Navbar 或 List 类的实例)。我们创建一个 Creator 的实例,通过实例去调用之后 startBuild 方法,之后就可以把复杂的对象一步步创建出来了。

class Navbar {
    init() {
        console.log("navbar-init");
    }

    getData() {
        console.log("navbar-getData");
        return new Promise((resolve) => {
            setTimeout(() => {
                resolve('navbar-zahuopu');
            }, 1000);
        })
    }

    render() {
        console.log("navbar-render");
    }
}

class List {
    init() {
        console.log("list-init");
    }

    getData() {
        console.log("list-getData");
        return new Promise((resolve) => {
            setTimeout(() => {
                resolve('list-zahuopu');
            }, 1000);
        })
    }

    render() {
        console.log("list-render");
    }
}

class Creator {
    async startBuild(builder) {
        await builder.init();
        await builder.getData();
        await builder.render();
    }
}

const op = new Creator();
op.startBuild(new Navbar());
op.startBuild(new List());

在这里插入图片描述


🎉🎉本篇小结

简单工厂模式和抽象工厂模式都隶属于设计模式中的 创建型模式

简单工厂模式是 由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

抽象工厂模式是指 当有多个抽象角色时使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体情况下,创建多个产品族中的产品对象。

建造者模式 将一个复杂对象的构建层与其表示层相互分离,同样的构建过程可采用不同的表示。工厂模式主要是为了创建对象实例或者类簇(抽象工厂),关心的最终产出的是什么,而不关心创建的过程。而建造者模式关心的是创建这个对象的整个过程,甚至于创建对象的每一个细节。

好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!


参考资料:

  1. 菜鸟教程 · 抽象工厂模式
  2. 百度百科 · 简单工厂模式,抽象工厂模式
  3. JavaScript设计模式 【作者:千锋教育】

在这里插入图片描述


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

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

相关文章

pdfh5在线预览pdf文件

前言 pc浏览器和ios的浏览器都可以直接在线显示pdf文件&#xff0c;但是android浏览器不能在线预览pdf文件&#xff0c;如何预览pdf文件&#xff1f; Github: https://github.com/gjTool/pdfh5 Gitee: https://gitee.com/gjTool/pdfh5 使用pdfh5预览pdf 编写预览页面 <…

Spring Framework 学习笔记1:基础

Spring Framework 学习笔记1&#xff1a;基础 1.简介 1.1.生态和发展史 关于 Spring 的生态和发展史&#xff0c;可以观看这个视频。 1.2.系统架构 关于 Spring 的系统架构&#xff0c;可以观看这个视频。 2.Ioc Spring 的核心概念是 Ioc &#xff08;Inversion Of Cont…

grafana8.3创建告警规则

1. 部署grafana的配置文件修改 因为要采用发送邮件的方式通知告警内容所以&#xff0c;在部署grafana时要先配置好SMTP / Emailing的内容&#xff1a; [smtp]enabled true # 开启smtphost smtp.mxhichina.com:465 #设置邮箱服务器地址user testtest.com #设置邮箱用户pas…

Flink SQL你用了吗?

分析&回答 Flink 1.1.0&#xff1a;第一次引入 SQL 模块&#xff0c;并且提供 TableAPI&#xff0c;当然&#xff0c;这时候的功能还非常有限。Flink 1.3.0&#xff1a;在 Streaming SQL 上支持了 Retractions&#xff0c;显著提高了 Streaming SQL 的易用性&#xff0c;使…

排序之选择排序

文章目录 前言一、直接选择排序1、直接选择排序基本思想2、直接选择排序代码实现3、直接选择排序的效率 二、堆排序1、堆排序2、堆排序的效率 前言 选择排序的基本思想就是每一次从待排序的数据元素中选出最小(或最大)的一个元素&#xff0c;存放在序列的起始位置&#xff0c;…

汇编--int指令

中断信息可以来自CPU的内部和外部&#xff0c; 当CPU的内部有需要处理的事情发生的时候&#xff0c;将产生需要马上处理的中断信息&#xff0c;引发中断过程。在http://t.csdn.cn/jihpG&#xff0c;我们讲解了中断过程和两种内中断的处理。 这一章中&#xff0c; 我们讲解另一种…

freemarker学习+集成springboot+导出word

目录 一 FreeMarker简介 二 集成springboot&#xff0c;实现案例导出 三 常见面试题总结 一 FreeMarker简介 FreeMarker 是一款 模板引擎&#xff1a; 即一种基于模板和要改变的数据&#xff0c; 并用来生成输出文本(HTML网页&#xff0c;电子邮件&#xff0c;配置文件&…

2024河南光伏展|河南储能展|河南国际太阳能光伏储能展览会

2024第四届中国&#xff08;郑州&#xff09;太阳能光伏及储能产业展览会 时间&#xff1a;2024年2月26-28日 地点&#xff1a;郑州.中原国际博览中心 河南国际太阳能光伏及储能产业展览会是一个盛大的行业聚会&#xff0c;旨在展示、交流、合作和创新。这个展览会将会是一个…

MATLAB中residue函数用法

目录 语法 说明 示例 求解具有实根的部分分式展开式 展开具有复数根和同次分子及分母的分式 展开分子次数高于分母次数的分式 residue函数的功能是部分分式展开&#xff08;部分分式分解&#xff09;。 语法 [r,p,k] residue(b,a) [b,a] residue(r,p,k) 说明 [r,p…

echarts饼图点击区块事件

效果图&#xff1a; 代码&#xff1a; let option {color: pieColors,series: [{name: Access From,type: pie,radius: [36%, 56%],avoidLabelOverlap: false,label: {formatter: params > {// console.log(params)return {color${params.dataIndex}|${params.name}(${par…

Scala集合继承体系图

Scala集合简介 1&#xff09; Scala 的集合有三大类&#xff1a;序列 Seq、集Set、映射 Map&#xff0c;所有的集合都扩展自 Iterable特质。 2&#xff09; 对于几乎所有的集合类&#xff0c;Scala 都同时提供了可变和不可变的版本&#xff0c;分别位于以下两个包 不可变集合…

软件确认测试的依据有哪些

确认测试 随着我国软件市场的日益繁荣和软件产品的大量涌现,软件评测的重要性越来越显现出来了。 一、确认测试的作用 1、软件确认测试对保障软件产品质量,开拓国际软件市场,促进软件市场健康发展都将发挥重要作用。 2、确认测试的目的是要表明软件是可以工作的&#xff0c…

【Nacos】2023.9.1 最新Nacos源码启动教程 | 超详细 | 包含踩坑经历和解决办法

在官网下载Nacos源码压缩包&#xff0c;或者使用git克隆到本地&#xff0c;使用IDEA打开项目。 Nacos GitHub地址 修改项目的jdk版本为1.8&#xff0c;修改maven使用的jdk版本也是1.8 打开最外边的pom文件&#xff0c;注释掉代码规范检查的插件&#xff08;nacos源码有些impor…

机器学习——聚类算法一

机器学习——聚类算法一 文章目录 前言一、基于numpy实现聚类二、K-Means聚类2.1. 原理2.2. 代码实现2.3. 局限性 三、层次聚类3.1. 原理3.2. 代码实现 四、DBSCAN算法4.1. 原理4.2. 代码实现 五、区别与相同点1. 区别&#xff1a;2. 相同点&#xff1a; 总结 前言 在机器学习…

springboot+activiti5.0整合(工作流引擎)

概述 springboot整合activiti使用modeler进行流程创建&#xff0c;编辑、部署以及删除实例&#xff08;可运行&#xff09; 详细 1、现在来说一下流程&#xff0c;先建立spring boot项目&#xff0c;导入对应的jar包。 <dependencies><dependency><groupId&…

Java 循环语句解析:从小白到循环达人

如果你正在学习编程&#xff0c;那么循环语句是一个绕不开的重要话题。循环语句让我们能够重复执行一段代码&#xff0c;从而实现各种各样的功能。在本篇博客中&#xff0c;我们将围绕 Java 编程语言中的循环语句展开&#xff0c;从最基础的概念出发&#xff0c;一步步引领你从…

Qt日历控件示例-QCalendarWidget

基本说明 QCalendarWidget介绍&#xff1a; QCalendarWidget 是 Qt 框架中提供的一个日期选择控件,用户可以通过该控件快速选择需要的日期,并且支持显示当前月份的日历。 这里&#xff0c;我们继承了QCalendarWidget&#xff0c;做了一些简单封装和样式调整 1.使用的IDE&…

java_error_in_idea.hprof 文件

在用户目录下的java_error_in_idea.hprof文件(/Users/用户) 大约1.5个G,IDEA的错误日志,可以删除

shiny根据数据的长度设置多个色板

shiny根据数据的长度设置多个色板 library(shiny) library(colourpicker) ui <- fluidPage(# 添加一个选择颜色的下拉菜单uiOutput("color_dropdown") )server <- function(input, output) {# 数据长度data_length <- reactive({length(c("数据1"…

Linux(centos) 下 Mysql 环境安装

linux 下进行环境安装相对比较简单&#xff0c;可还是会遇到各种奇奇怪怪的问题&#xff0c;我们来梳理一波 安装 mysql 我们会用到下地址&#xff1a; Mysql 官方文档的地址&#xff0c;可以参考&#xff0c;不要全部使用 https://dev.mysql.com/doc/refman/8.0/en/linux-i…