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

个人简介

👀个人主页: 前端杂货铺

🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展

📃个人状态: 研发工程师,现效力于中国工业软件事业

🚀人生格言: 积跬步至千里,积小流成江海

🥇推荐学习:🍍前端面试宝典 🍉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"

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

javascript 复制代码
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 返回相应的类进行权限分配。

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

javascript 复制代码
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 方法,之后就可以把复杂的对象一步步创建出来了。

javascript 复制代码
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设计模式 【作者:千锋教育】


相关推荐
linweidong5 分钟前
中科曙光Java后端开发面试题及参考答案
分布式·设计模式·spring mvc·tcp协议·三次握手·后端开发·java面经
爱吃香菜i17 分钟前
数据连接开发设计文档
前端·javascript
冴羽19 分钟前
现代 CSS 颜色使用指南
前端·javascript·css
Rrvive19 分钟前
Vue3向全局广播数据变化
javascript·vue.js
han_26 分钟前
为啥 Array.isArray 判断数组最靠谱?
前端·javascript
老蒋每日coding44 分钟前
AI智能体设计模式系列(五)—— 工具使用模式
人工智能·设计模式
梦6501 小时前
Vue3 计算属性 (computed) 与监听属性 (watch)
前端·javascript·vue.js
六月June June1 小时前
leaflet L.popup().setContent中挂载vue组件
前端·javascript·vue.js
软件开发技术深度爱好者1 小时前
JavaScript的p5.js库使用详解(上)
开发语言·javascript
首席拯救HMI官1 小时前
【拯救HMI】HMI容错设计:如何减少操作失误并快速纠错?
大数据·运维·前端·javascript·网络·学习