js设计模式【详解】—— 工厂模式

简介: js设计模式【详解】—— 工厂模式

工厂模式定义

用途: 创建对象

核心思想:不暴露创建对象的具体逻辑,将逻辑封装在一个函数中,这个函数就可以被视为一个工厂。

分类(根据抽象程度的不同):简单工厂(又叫静态工厂模式),工厂方法和抽象工厂

简单工厂【重点掌握】

使用场景:创建的对象数量较少,对象的创建逻辑不复杂时使用。(在实际的前端业务中,最常用的简单工厂模式。如果不是超大型的项目,是很难有机会使用到工厂方法模式和抽象工厂方法模式的。)

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

缺点:每增加新的构造函数还需要修改判断逻辑代码。

演示范例——简单工厂

范例功能:根据用户的权限来渲染不同的页面

实现思路:使用关键字class定义类User,此时的User类就是一个简单工厂,调用工厂方法,传入不同的参数,便能得到拥有不同权限的用户实例

//User类
class User {
  //构造器
  constructor(opt) {
    this.name = opt.name;
    this.viewPage = opt.viewPage;
  }
 
  //静态方法
  static getInstance(role) {
    switch (role) {
      case 'superAdmin':
        return new User({ name: '超级管理员', viewPage: ['首页', '通讯录', '发现页', '应用数据', '权限管理'] });
        break;
      case 'admin':
        return new User({ name: '管理员', viewPage: ['首页', '通讯录', '发现页', '应用数据'] });
        break;
      case 'user':
        return new User({ name: '普通用户', viewPage: ['首页', '通讯录', '发现页'] });
        break;
      default:
        throw new Error('参数错误, 可选参数:superAdmin、admin、user')
    }
  }
}
 
//调用
let superAdmin = User.getInstance('superAdmin');
let admin = User.getInstance('admin');
let normalUser = User.getInstance('user');

项目实战范例——简单工厂

范例功能:在登录的时候根据权限使用vue-router提供的addRoutes方法给予用户相对应的路由权限。

router/index.js文件

//index.js
 
import Vue from 'vue'
import Router from 'vue-router'
import Login from '../components/Login.vue'
 
Vue.use(Router)
 
export default new Router({
  routes: [
    //重定向到登录页
    {
      path: '/',
      redirect: '/login'
    },
    //登陆页
    {
      path: '/login',
      name: 'Login',
      component: Login
    }
  ]
})

router/文件夹下新建一个routerFactory.js文件,导出routerFactory简单工厂函数,用于根据用户权限提供路由权限

//routerFactory.js
 
import SuperAdmin from '../components/SuperAdmin.vue'
import NormalAdmin from '../components/Admin.vue'
import User from '../components/User.vue'
import NotFound404 from '../components/404.vue'
 
let AllRoute = [
  //超级管理员页面
  {
    path: '/super-admin',
    name: 'SuperAdmin',
    component: SuperAdmin
  },
  //普通管理员页面
  {
    path: '/normal-admin',
    name: 'NormalAdmin',
    component: NormalAdmin
  },
  //普通用户页面
  {
    path: '/user',
    name: 'User',
    component: User
  },
  //404页面
  {
    path: '*',
    name: 'NotFound404',
    component: NotFound404
  }
]
 
let routerFactory = (role) => {
  switch (role) {
    case 'superAdmin':
      return {
        name: 'SuperAdmin',
        route: AllRoute
      };
      break;
    case 'normalAdmin':
      return {
        name: 'NormalAdmin',
        route: AllRoute.splice(1)
      }
      break;
    case 'user':
      return {
        name: 'User',
        route:  AllRoute.splice(2)
      }
      break;
    default: 
      throw new Error('参数错误! 可选参数: superAdmin, normalAdmin, user')
  }
}
 
export { routerFactory }

在登录页导入该方法,请求登录接口后根据权限添加路由:

//Login.vue
 
import {routerFactory} from '../router/routerFactory.js'
export default {
  //... 
  methods: {
    userLogin() {
      //请求登陆接口, 获取用户权限, 根据权限调用this.getRoute方法
      //..
    },
    
    getRoute(role) {
      //根据权限调用routerFactory方法
      let routerObj = routerFactory(role);
      
      //给vue-router添加该权限所拥有的路由页面
      this.$router.addRoutes(routerObj.route);
      
      //跳转到相应页面
      this.$router.push({name: routerObj.name})
    }
  }
};

使用this.$router.addRoutes方法添加的路由刷新后不能保存,所以会导致路由无法访问。通常的做法是本地加密保存用户信息,在刷新后获取本地权限并解密,根据权限重新添加路由。

工厂方法

核心要点:将创建实例推迟到子类中进行;

实现原理:使用new.target来模拟出抽象类。new.target指向直接被new执行的构造函数,我们对new.target进行判断,如果指向了该类则抛出错误来使得该类成为抽象类。

class User {
  constructor(name = '', viewPage = []) {
    if(new.target === User) {
      throw new Error('抽象类不能实例化!');
    }
    this.name = name;
    this.viewPage = viewPage;
  }
}
 
class UserFactory extends User {
  constructor(name, viewPage) {
    super(name, viewPage)
  }
  create(role) {
    switch (role) {
      case 'superAdmin': 
        return new UserFactory( '超级管理员', ['首页', '通讯录', '发现页', '应用数据', '权限管理'] );
        break;
      case 'admin':
        return new UserFactory( '普通用户', ['首页', '通讯录', '发现页'] );
        break;
      case 'user':
        return new UserFactory( '普通用户', ['首页', '通讯录', '发现页'] );
        break;
      default:
        throw new Error('参数错误, 可选参数:superAdmin、admin、user')
    }
  }
}
 
let userFactory = new UserFactory();
let superAdmin = userFactory.create('superAdmin');
let admin = userFactory.create('admin');
let user = userFactory.create('user');

抽象工厂

抽象工厂模式是对类的工厂抽象用来创建产品类簇,不负责创建某一类产品的实例。

同样使用new.target语法来模拟抽象类,并通过继承的方式创建出UserOfWechat, UserOfQq, UserOfWeibo这一系列子类类簇。使用getAbstractUserFactor来返回指定的类簇。

class User {
  constructor(type) {
    if (new.target === User) {
      throw new Error('抽象类不能实例化!')
    }
    this.type = type;
  }
}
 
class UserOfWechat extends User {
  constructor(name) {
    super('wechat');
    this.name = name;
    this.viewPage = ['首页', '通讯录', '发现页']
  }
}
 
class UserOfQq extends User {
  constructor(name) {
    super('qq');
    this.name = name;
    this.viewPage = ['首页', '通讯录', '发现页']
  }
}
 
class UserOfWeibo extends User {
  constructor(name) {
    super('weibo');
    this.name = name;
    this.viewPage = ['首页', '通讯录', '发现页']
  }
}
 
function getAbstractUserFactory(type) {
  switch (type) {
    case 'wechat':
      return UserOfWechat;
      break;
    case 'qq':
      return UserOfQq;
      break;
    case 'weibo':
      return UserOfWeibo;
      break;
    default:
      throw new Error('参数错误, 可选参数:superAdmin、admin、user')
  }
}
 
let WechatUserClass = getAbstractUserFactory('wechat');
let QqUserClass = getAbstractUserFactory('qq');
let WeiboUserClass = getAbstractUserFactory('weibo');
 
let wechatUser = new WechatUserClass('微信小李');
let qqUser = new QqUserClass('QQ小李');
let weiboUser = new WeiboUserClass('微博小李');

更多设计模式详见——js设计模式【详解】总目录

https://blog.csdn.net/weixin_41192489/article/details/116154815

目录
相关文章
|
1月前
|
设计模式 JavaScript 前端开发
JavaScript设计模式--访问者模式
【10月更文挑战第1天】
31 3
|
3月前
|
设计模式 JavaScript 前端开发
从工厂到单例再到策略:Vue.js高效应用JavaScript设计模式
【8月更文挑战第30天】在现代Web开发中,结合使用JavaScript设计模式与框架如Vue.js能显著提升代码质量和项目的可维护性。本文探讨了常见JavaScript设计模式及其在Vue.js中的应用。通过具体示例介绍了工厂模式、单例模式和策略模式的应用场景及其实现方法。例如,工厂模式通过`NavFactory`根据用户角色动态创建不同的导航栏组件;单例模式则通过全局事件总线`eventBus`实现跨组件通信;策略模式用于处理不同的表单验证规则。这些设计模式的应用不仅提高了代码的复用性和灵活性,还增强了Vue应用的整体质量。
51 1
|
3月前
|
设计模式 JavaScript 前端开发
小白请看 JS大项目宝典:设计模式 教你如何追到心仪的女神
小白请看 JS大项目宝典:设计模式 教你如何追到心仪的女神
|
4月前
|
设计模式 JavaScript
js设计模式【详解】—— 桥接模式
js设计模式【详解】—— 桥接模式
70 6
|
4月前
|
设计模式 JavaScript 前端开发
JavaScript进阶 - JavaScript设计模式
【7月更文挑战第7天】在软件工程中,设计模式是解决常见问题的标准解决方案。JavaScript中的工厂模式用于对象创建,但过度使用可能导致抽象过度和缺乏灵活性。单例模式确保唯一实例,但应注意避免全局状态和过度使用。观察者模式实现了一对多依赖,需警惕性能影响和循环依赖。通过理解模式的优缺点,能提升代码质量。例如,工厂模式通过`createShape`函数动态创建对象;单例模式用闭包保证唯一实例;观察者模式让主题对象通知多个观察者。设计模式的恰当运用能增强代码可维护性。
81 0
|
4月前
|
设计模式 缓存 JavaScript
js设计模式实例
【7月更文挑战第2天】JavaScript设计模式包含工厂、单例、建造者、抽象工厂和代理模式等,它们是最佳实践和可重用模板,解决创建、职责分配和通信等问题。例如,工厂模式封装对象创建,单例确保全局唯一实例,建造者模式用于复杂对象构建,抽象工厂创建相关对象集合,而代理模式则控制对象访问。这些模式提升代码质量、可读性和灵活性,是高效开发的关键。
37 0
|
17天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
|
2月前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。
|
19天前
|
设计模式 开发者 Python
Python编程中的设计模式:工厂方法模式###
本文深入浅出地探讨了Python编程中的一种重要设计模式——工厂方法模式。通过具体案例和代码示例,我们将了解工厂方法模式的定义、应用场景、实现步骤以及其优势与潜在缺点。无论你是Python新手还是有经验的开发者,都能从本文中获得关于如何在实际项目中有效应用工厂方法模式的启发。 ###
|
12天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
31 1