【设计模式】工厂模式和抽象工厂模式

工厂模式

js 复制代码
function User(role, pages) {
    this.role = role;
    this.pages = pages;
}

// new User('admin', ['home', 'user', 'setting']);
// new User('user', ['home', 'user']);
// new User('guest', ['home']);

function UserFactory(role) {
    switch (role) {
        case 'admin':
            return new User(role, ['home', 'user', 'setting']);
            break;
        case 'user':
            return new User(role, ['home', 'user']);
            break;
        case 'guest':
            return new User(role, ['home']);
            break;
        default:
            throw new Error('未知角色')
    }
}

es6 的写法:

js 复制代码
class User {
    constructor(role, pages) {
        this.role = role;
        this.pages = pages;
    }
    static getInstance(role) {
        switch (role) {
            case 'admin':
                return new User(role, ['home', 'user', 'setting']);
                break;
            case 'user':
                return new User(role, ['home', 'user']);
                break;
            case 'guest':
                return new User(role, ['home']);
                break;
            default:
                throw new Error('未知角色')
        }
    }
}

User.getInstance('admin'); // {role: 'admin', pages: ['home', 'user', 'setting']}

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

但是在函数内包含了所有对象的创建逻辑和判断逻辑的代码,每增加新的构造函数还需要修改判断逻辑代码。当我们的对象不是上面的3个而是10个或更多时,这个函数会成为一个庞大的超级函数,变得难以维护。

所以,简单工厂只能作用于创建的对象数量较少,对象的创建逻辑不复杂时使用。

抽象工厂模式

js 复制代码
class User {
    constructor(name, role, pages) {
        this.name = name;
        this.role = role;
        this.pages = pages;
    }

    welcome() {
        console.log(`欢迎${this.name}使用本系统`)
    }

    showPage() {
        // js 中没有内置的 abstract
        throw new Error(`请实现 showPage 方法`)
    }
}

class SuperAdmin extends User {
    constructor(name) {
        super(name, 'superAdmin', ['home', 'user', 'setting']);
    }

    showPage() {
        console.log(`超级管理员拥有以下页面:${this.pages.join(' ')}`)
    }

    addUser() {
        console.log(`添加用户`)
    }

    addRight() {
        console.log(`添加权限`)
    }
}

class Editor extends User {
    constructor(name) {
        super(name, 'editor', ['home', 'user']);
    }

    showPage() {
        console.log(`编辑拥有以下页面:${this.pages.join(' ')}`)
    }

}
function getAbstractUserFactory(role) {
    switch (role) {
        case 'superAdmin':
            return SuperAdmin;
        case 'editor':
            return Editor;
        default:
            throw new Error(`没有找到对应的角色`)
    }
}
const userClass = getAbstractUserFactory('editor');
const user = new userClass('张三');
user.showPage(); // 编辑拥有以下页面:home user
相关推荐
腾讯TNTWeb前端团队6 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
千千寰宇9 小时前
[设计模式/Java/多线程] 设计模式之单例模式【9】
设计模式·操作系统-进程/线程/并发
范文杰10 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪10 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪10 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy11 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom11 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom11 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom11 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom11 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试