目录
工厂模式定义
简单工厂【重点掌握】
演示范例——简单工厂
项目实战范例——简单工厂
工厂方法
抽象工厂
工厂模式定义
用途: 创建对象
核心思想:不暴露创建对象的具体逻辑,将逻辑封装在一个函数中,这个函数就可以被视为一个工厂。
分类(根据抽象程度的不同):简单工厂(又叫静态工厂模式),工厂方法和抽象工厂
简单工厂【重点掌握】
使用场景:创建的对象数量较少,对象的创建逻辑不复杂时使用。(在实际的前端业务中,最常用的简单工厂模式。如果不是超大型的项目,是很难有机会使用到工厂方法模式和抽象工厂方法模式的。)
优点:只需要一个正确的参数,就可以获取到你所需要的对象,而无需知道其创建的具体细节。
缺点:每增加新的构造函数还需要修改判断逻辑代码。
演示范例——简单工厂
范例功能:根据用户的权限来渲染不同的页面
实现思路:使用关键字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');
抽象工厂
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('微博小李');