react 前端框架如何驱动企业数字化转型与创新发展
685
2022-11-15
前端常用设计模式
一、单例模式
定义:保证一个类只有一个实例,并且提供一个访问它的全局访问点。 使用场景:一些对象我们往往只需要一个,比如线程池、全局缓存、浏览器中的window对象、登录浮窗等。 实现:用一个变量标识当前是否已经为某个类创建过对象,如果是,则在下一次获取这个类的实例时,直接返回之前创建的对象。 优点:可以用来划分命令空间,减少全局变量的数量。 可以被实例化,且实例化一次,再次实例化生成的也是第一个实例。
1. 例子1
//单例模式var Singleton = function(name) { this.name = name this.instance = null};Singleton.prototype.getName = function() { return this.name;};// 获取实例对象Singleton.getInstance = function(name) { if (!this.instance) { this.instance = new Singleton(name) } return this.instance } //测试单例模式的实例var a = Singleton.getInstance('aa')var b = Singleton.getInstance('bb')console.log(a === b); // true
2.例子2
(function() { // 管理单例的逻辑代码,如果没有数据则创建,有数据则返回 var getSingle = function(fn) { // 参数为创建对象的方法 var result; return function() { // 判断是null 或赋值 return result || (result = fn.apply(this, arguments)) }; }; // 创建登录窗口方法 var createLoginLayer = function() { var div = document.createElement('div'); div.innerHTML = '我是登录浮窗' div.style.display = 'none' document.body.appendChild(div) return div; }; // 单例方法 var createSingleLoginLayer = getSingle(createLoginLayer) // 使用惰性单例,进行创建 document.getElementById('loginBtn').onlick = function() { var loginLayer = createSingleLoginLayer(); loginLayer.style.display = 'block' };})()
二、观察者模式
定义:对象间的一种一对多的依赖关系。 使用场景:当一个对象的状态发生变化时,所有依赖于他的对象都将得到通知。 优点:时间上的解耦,对象之间的解耦。 实现:
首先,指定好谁充当发布者;然后,给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者;最后,发布消息时,发布者会遍历这个缓存列表,依次触发里面存放的订阅者回调函数。
1. 例子1
var salesOffices = {}; // 定义售楼处 salesOffices.clientList = []; // 缓存列表,存放订阅者的回调函数 salesOffices.listen = function(fn) { // 增加订阅者 this.clientList.push(fn) // 订阅的消息添加进缓存列表 }; salesOffices.trigger = function() { // 发布消息 for (var i = 0, fn; fn = this.clientList[i++];) { fn.apply(this, arguments); // arguments 是发布消息时带上的参数。 } }; //调用 salesOffices.listen(function(price,) { // 订阅消息 console.log('价格=' + price); console.log('squareMeter=' + squareMeter); }); salesOffices.trigger(2000000, 88); // 输出: 200 万,88 平方米
2. 例子2
登录页面后,需要刷新各个模块的信息(头像,nav)。
var ObserverEvent = (function() { var clientList = [], listen, trigger, remove; listen = function(key,) { if (!clientList[key]) { clientList[key] = []; } clientList[key].push(fn); }; trigger = function() { var key = Array.prototype.shift.call(arguments), fns = clientList[key]; if (!fns || fns.length === 0) { return false } for (var i = 0, fn; fn = fns[i++];) { fn.apply(this, arguments) } }; remove = function(key,) { var fns = clientList[key]; if (!fns) { return false } if (!fn) { fns && (fns.length = 0) } else { for (var l = fns.length - 1; l >= 0; l--) { var _fn = fns[l]; if (_fn === fn) { fns.splice(l, 1); } } } }; return { listen: listen, trigger: trigger, remove: remove } })(); ObserverEvent.listen('squareMeter88', fn1 = function(price) { console.log('价格=' + price); }); ObserverEvent.listen('squareMeter100', function(price) { console.log('价格=' + price); }); ObserverEvent.trigger('squareMeter88', 200000); //刷新模块信息 var header = (function() { ObserverEvent.listen('loginSucc', function(data) { header.setAvatar(data.avatar); }); return { setAvatar: function(data) { console.log(data + "设置header成功"); } } })(); var nav = (function() { ObserverEvent.listen('loginSucc', function(data) { nav.setAvatar(data.avatar) }); return { setAvatar: function(data) { console.log(data + '设置nav成功'); } } })(); var data = {}; data.avatar = '参数'; ObserverEvent.trigger('loginSucc', data)
三、工厂模式
定义:将其成员对象的实例化推迟到子类来实现的类。 需求:创建对象的流程赋值的时候,比如依赖很多设置文件等;处理大量具有相同属性的小对象;注意:不能滥用。 分类:简单工厂,工厂方法和抽象工厂。
(一)简单工厂模式(创建单一对象,需要的类比较少)
let UserFactory = function(role) { function SuperAdmin() { this.name = '超级管理员'; this.viewPage = ['首页', '通讯录', '发现页', '应用数据', '权限管理'] } function Admin() { this.name = '管理员'; this.viewPage = ['首页', '通讯录', '发现页'] console.log(this.name, this.viewPage); } function NormalUser() { this.name = '普通用户'; this.viewPage = ['首页', '通讯录', '发现页'] } switch (role) { case 'superAdmin': return new SuperAdmin(); break; case 'admin': return new Admin(); break; case 'user': return new NormalUser(); break; default: throw new Error('参数错误,可选参数:superAdmin,admin,user') }}UserFactory('admin');
(二)工厂方法模式(创建多类对象,需要的类比较多)
为方便后续新增类方便,只需改一处代码,封装了工厂方法而已。并且把类都放在工厂类原型中实现。
// 安全模式创建的工厂方法函数 let UserFactory = function(role) { if (this instanceof UserFactory) { var s = new this[role](); return s; } else { return new UserFactory(role); } } // 工厂方法函数的原型中设置所有对象的构造函数 UserFactory.prototype = { SuperAdmin: function() { this.name = '超级管理员' this.viewPage = ['首页', '通讯录', '发现页', '应用数据', '权限管理'] }, Admin: function() { this.name = '管理员'; this.viewPage = ['首页', '通讯录', '发现页', '应用数据'] }, NormalUser: function() { this.name = '普通用户'; this.viewPage = ['首页', '通讯录', '发现页'] } } // 调用 let superAdmin = UserFactory('SuperAdmin') let admin = UserFactory('Admin') let NormalUser = UserFactory('NormalUser')
(三)抽象工厂模式
创建父类,子类继承父类,具体实现在子类。 抽象工厂其实是实现子类继承父类的方法,只是一个方法。 抽象工厂模式一般用在多人协作的超大型项目中,并且严格的要求项目以面向对象的思想进行完成。
// 抽象工厂方法var VehicleFactory = function(subType,) { // 判断抽象工厂中是否有该抽象类 if (typeof VehicleFactory[superType] === 'function') { // 缓存类 function F() {}; // 继承父类属性和方法 F.prototype = new VehicleFactory[superType](); // 将子类构造函数指向子类 subType.constructor = subType // 子类原型继承父类 subType.prototype = new F() } else { // 不存在该抽象类抛出错误 throw new Error('未创建该抽象类') }};// 小汽车抽象类VehicleFactory.Car = function() { this.type = 'car';};VehicleFactory.Car.prototype = { getPrice: function() { return new Error('抽象方法不能调用') }, getSpeed: function() { return new Error('抽象方法不能调用') }};// 公交车抽象类VehicleFactory.Bus = function() { this.type = 'bus'};VehicleFactory.Bus.prototype = { getPrice: function() { return new Error('抽象方法不能调用') }, getSpeed: function() { return new Error('抽象方法不能调用') }};// 货车抽象类VehicleFactory.Truck = function() { this.type = 'truck'};VehicleFactory.Truck.prototype = { getPrice: function() { return new Error('抽象方法不能调用'); }, getSpeed: function() { return new Error('抽象方法不能调用') }};// 使用:创建产品子类继承相应的产品组抽象类// 宝马汽车子类var BMW = function(price,) { this.price = price this.speed = speed}// 抽象工厂实现对Car抽象类的继承VehicleFactory(BMW, 'Car');BMW.prototype.getPrice = function() { return this.price}BMW.prototype.getSpeed = function() { return this.speed}// 公交车...// 货车...
四、命令模式
定义: 用来对方法调用进行参数化处理和传送,经过这样处理过的方法调用可以在任何需要的时候进行执行。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~