时间:2023-09-11 16:24:02 | 来源:网站运营
时间:2023-09-11 16:24:02 来源:网站运营
掌握前端5大常用设计模式,瞬间高大上:主要介绍一下我们平常会经常用到的设计模式,设计模式总的来说有23种,而设计模式在前端中又该怎么运用呢,接下来主要对比较前端中常见的设计模式做一个介绍let UserFactory = function (role) { function SuperAdmin() { this.name = "超级管理员", this.viewPage = ['首页', '用户管理', '订单管理', '应用管理', '权限管理'] } function Admin() { 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'); }}//调用let superAdmin = UserFactory('superAdmin');let admin = UserFactory('admin')let normalUser = UserFactory('user')
总结:在上面的例子中,UserFactory就是一个简单工厂,在该函数中有3个构造函数分别对应不同的权限的用户,当我们调用工厂函数时,只需要传递superAdmin, admin, user这三个可选参数中的一个获取对应的实例对象//安全模式创建的工厂方法函数 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')
总结:在简单工厂中,如果我们新增加一个用户类型,需要修改两个地方的代码,一个是增加新的用户构造函数,一个是在逻辑判断中增加对新的用户的判断,而在抽象工厂方法中,我们只需要在UserFactory.prototype中添加就可以啦。var single = (function(){ var unique; function getInstance(){ // 如果该实例存在,则直接返回,否则就对其实例化 if( unique === undefined ){ unique = new Construct(); } return unique; } function Construct(){ // ... 生成单例的构造函数的代码 } return { getInstance : getInstance } })();
总结:在上面的代码中,我们可以使用single.getInstance来获取到单例,并且每次调用均获取到同一个单例,在我们平时的开发中,我们也经常会用到这种模式,比如当我们单击登录按钮的时候,页面中会出现一个登录框,而这个浮窗是唯一的,无论单击多少次登录按钮,这个浮窗只会被创建一次,因此这个登录浮窗就适合用单例模式。(function(){ // 示例代码 // 目标对象,是真正被代理的对象 function Subject(){} Subject.prototype.request = function(){}; /** * 代理对象 * @param {Object} realSubject [持有被代理的具体的目标对象] */ function Proxy(realSubject){ this.realSubject = readSubject; } Proxy.prototype.request = function(){ this.realSubject.request(); }; }());
总结:在上面的代码中,Proxy可以控制对真正被代理对象的一个访问,在代理模式中,比较常见的就是虚拟代理,虚拟代理用于控制对那种创建开销很大的本体的访问,它会把本体的实例化推迟到有方法被调用的时候,比如说,现在我们假设PublicLibrary的实例化很慢,不能在网页加载的时候立即完成,我们可以为其创建一个虚拟代理,让它把PublicLibrary的实例化推迟到必要的时候,比如说我们在前端中经常用到的图片懒加载,就可以用虚拟代理;document.body.addEventListener("click", function() { alert("Hello World") },false ) document.body.click() //模拟用户点击
总结:在上面的例子中,需要监听用户点击 document.body 的动作,但是我们是没办法预知用户将在什么时候点击的,因此我们订阅了 document.body 的 click 事件,当 body 节点被点击时,body 节点便会向订阅者发布 “Hello World” 消息。function Price(personType, price) { //vip 5 折 if (personType == 'vip') { return price * 0.5; } else if (personType == 'old'){ //老客户 3 折 return price * 0.3; } else { return price; //其他都全价 } }
在上面的代码中,我们需要很多个判断,如果有很多优惠,我们又需要添加很多判断,这里已经违背了刚才说的设计模式的六大原则中的开闭原则了,如果使用策略模式,我们的代码可以这样写:// 对于vip客户 function vipPrice() { this.discount = 0.5; } vipPrice.prototype.getPrice = function(price) { return price * this.discount; } // 对于老客户 function oldPrice() { this.discount = 0.3; } oldPrice.prototype.getPrice = function(price) { return price * this.discount; } // 对于普通客户 function Price() { this.discount = 1; } Price.prototype.getPrice = function(price) { return price ; } // 上下文,对于客户端的使用 function Context() { this.name = ''; this.strategy = null; this.price = 0; } Context.prototype.set = function(name, strategy, price) { this.name = name; this.strategy = strategy; this.price = price; } Context.prototype.getResult = function() { console.log(this.name + ' 的结账价为: ' + this.strategy.getPrice(this.price)); } var context = new Context(); var vip = new vipPrice(); context.set ('vip客户', vip, 200); context.getResult(); // vip客户 的结账价为: 100 var old = new oldPrice(); context.set ('老客户', old, 200); context.getResult(); // 老客户 的结账价为: 60 var Price = new Price(); context.set ('普通客户', Price, 200); context.getResult(); // 普通客户 的结账价为: 200
总结:在上面的代码中,通过策略模式,使得客户的折扣与算法解藕,又使得修改跟扩展能独立的进行,不影到客户端或其他算法的使用。关键词:模式,高大,设计,掌握