摘要:小明追女神的故事小明遇到了他的女神,打算送一朵鲜花来表白。刚好小明打听到他和有一个共同的好友,于是小明决定让来替自己来完成这件事。
1.单例模式
单例模式的核心:
(1)确保只有一个实例
(2)提供全局访问
用代理实现单例模式:
var ProxySingletonCreateDiv = (function(){ var instance; return function( html ){ if ( !instance ){ instance = new CreateDiv( html ); } return instance; } })();
通用的惰性单例模式:创建登陆悬浮窗
//fn保存创建逻辑 //单例模式:只创建一次 var getSingle = function( fn ){ var result; return function(){ 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" ).onclick = function(){ var loginLayer = createSingleLoginLayer(); loginLayer.style.display = "block"; };2.发布-订阅者模式
(1)首先要指定好谁充当发布者
(2)然后给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者
(3)最后发布消息的时候,发布者会遍历这个缓存列表,依次触发里面存放的订阅者函数
var Event = (function(){ var clientList = {}, listen, trigger, remove; listen = function( key, fn ){ 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, fn ){ 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 } })();
给所有的对象都动态安装一个发布-订阅功能:
var installEvent = function( obj ){ for ( var i in event ){ obj[ i ] = event[ i ]; } };3.装饰着模式
(1)装饰者模式可以动态的给某个对象添加一些额外的职责,而不会影响从这个类中派生出的其他对象。
(2)装饰者也是包装器:装饰者模式将一个对象嵌入到另一个对象中,实际上相当于这个对象被另一个对象包装起来,形成一条包装链。
3-1.在不改变原来函数的情况下给函数增加新的功能
var a=function(){ alert(1); } var _a = a; a=function(){ _a(); alert(2); }
但是这样做会带来两个问题:必须维护_a这个中间变量;存在this被劫持的问题
3-2.用AOP装饰函数
Function.prototype.before = function( beforefn ){ var __self = this; // 保存原函数的引用 return function(){ // 返回包含了原函数和新函数的"代理"函数 beforefn.apply( this, arguments ); // 执行新函数,且保证this 不被劫持,新函数接受的参数 // 也会被原封不动地传入原函数,新函数在原函数之前执行 return __self.apply( this, arguments ); // 执行原函数并返回原函数的执行结果, // 并且保证this 不被劫持 } } Function.prototype.after = function( afterfn ){ var __self = this; return function(){ var ret = __self.apply( this, arguments ); afterfn.apply( this, arguments ); return ret; } }; //调用:重写原来函数 formSubmit = formSubmit.before( validata );4.策略模式
策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
4-1.使用策略模式计算奖金
绩效为S的人年终奖金是工资的4倍,绩效为A的人年终奖金是工资的3倍,绩效为B的人年终奖金是工资的2倍
var performanceS = function(){}; performanceS.prototype.calculate = function( salary ){ return salary * 4; }; var performanceA = function(){}; performanceA.prototype.calculate = function( salary ){ return salary * 3; }; var performanceB = function(){}; performanceB.prototype.calculate = function( salary ){ return salary * 2; }; //接下来定义奖金类Bonus: var Bonus = function(){ this.salary = null; // 原始工资 this.strategy = null; // 绩效等级对应的策略对象 }; Bonus.prototype.setSalary = function( salary ){ this.salary = salary; // 设置员工的原始工资 }; Bonus.prototype.setStrategy = function( strategy ){ this.strategy = strategy; // 设置员工绩效等级对应的策略对象 }; Bonus.prototype.getBonus = function(){ // 取得奖金数额 return this.strategy.calculate( this.salary ); // 把计算奖金的操作委托给对应的策略对象 }; var bonus = new Bonus(); bonus.setSalary( 10000 ); bonus.setStrategy( new performanceS() ); // 设置策略对象 console.log( bonus.getBonus() ); // 输出:40000
4-2.javascript版本的策略模式
var strategies = { "S": function( salary ){ return salary * 4; }, "A": function( salary ){ return salary * 3; }, "B": function( salary ){ return salary * 2; } }; var calculateBonus = function( level, salary ){ return strategies[ level ]( salary ); }; console.log( calculateBonus( "S", 20000 ) ); // 输出:80000 console.log( calculateBonus( "A", 10000 ) ); // 输出:30000
通过使用策略模式重构代码,我们消除了原来程序中大片的条件分支代码。所有和计算奖金的逻辑不再放在context中,而是分布在各个策略对象中。每个策略对象负责的算法已被各自封装在对象内部。当我们对这些策略对象发出“计算奖金”请求时,它们会返回各自不同的计算结果。
4-3.用策略模式进行表单校验
(1)用户名不能为空
(2)密码长度不能少于6位
(3)手机号码必须符合格式
5.代理模式
代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。
5-1.小明追女神的故事
小明遇到了他的女神A,打算送一朵鲜花来表白。刚好小明打听到他和A有一个共同的好友B,于是小明决定让B来替自己来完成这件事。
var Flower = function(){}; var xiaoming = { sendFlower: function( target ){ var flower = new Flower(); target.receiveFlower( flower ); } }; var A = { receiveFlower: function( flower ){ console.log( "收到花 " + flower ); } }; xiaoming.sendFlower( A ); //接下来,我们引入代理B,即小明通过B 来给A 送花: var Flower = function(){}; var xiaoming = { sendFlower: function( target){ var flower = new Flower(); target.receiveFlower( flower ); } }; var B = { receiveFlower: function( flower ){ A.receiveFlower( flower ); 90 第6 章 代理模式 } }; var A = { receiveFlower: function( flower ){ console.log( "收到花 " + flower ); } }; xiaoming.sendFlower( B ); //然后选择A 心情好的时候把花转交给A,代码如下: var Flower = function(){}; var xiaoming = { sendFlower: function( target){ var flower = new Flower(); target.receiveFlower( flower ); } }; var B = { receiveFlower: function( flower ){ A.listenGoodMood(function(){ // 监听A 的好心情 A.receiveFlower( flower ); }); } }; var A = { receiveFlower: function( flower ){ console.log( "收到花 " + flower ); }, listenGoodMood: function( fn ){ setTimeout(function(){ // 假设10 秒之后A 的心情变好 fn(); }, 10000 ); } }; xiaoming.sendFlower( B ); var myImage = (function(){ var imgNode = document.createElement( "img" ); document.body.appendChild( imgNode ); return { setSrc: function( src ){ imgNode.src = src; } } })();
5-2.保护代理与虚拟代理
保护代理:比如B可以帮助A过滤掉一些请求,如送花的人中年龄较大的
虚拟代理:new Flower可能是非常昂贵的,这时候需要B代理去执行,代理B在A心情好的时候再执行。
5-3.虚拟代理实现图片预加载
var myImage = (function(){ var imgNode = document.createElement( "img" ); document.body.appendChild( imgNode ); return function( src ){ imgNode.src = src; } })(); var proxyImage = (function(){ var img = new Image; img.onload = function(){ myImage( this.src ); } return function( src ){ myImage( "file:// /C:/Users/svenzeng/Desktop/loading.gif" ); img.src = src; } })(); proxyImage( "http:// imgcache.qq.com/music// N/k/000GGDys0yA0Nk.jpg" );
纵观整个程序,我们并没有改变或者增加myImage接口,但是通过代理对象,实际上是给系统添加了新的行为:给img节点设置 src和图片预加载这两个功能。
5-4.虚拟代理合并http请求
1 2 3 4 5 6 7 8 9
script.js:
var synchronousFile = function( id ){ console.log( "开始同步文件,id 为: " + id ); }; var proxySynchronousFile = (function(){ var cache = [], // 保存一段时间内需要同步的ID timer; // 定时器 return function( id ){ cache.push( id ); if ( timer ){ // 保证不会覆盖已经启动的定时器 return; } timer = setTimeout(function(){ synchronousFile( cache.join( "," ) ); // 2 秒后向本体发送需要同步的ID 集合 clearTimeout( timer ); // 清空定时器 timer = null; cache.length = 0; // 清空ID 集合 }, 2000 ); } })(); var checkbox = document.getElementsByTagName( "input" ); for ( var i = 0, c; c = checkbox[ i++ ]; ){ c.onclick = function(){ if ( this.checked === true ){ proxySynchronousFile( this.id ); } } };
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/82818.html
摘要:一开始我以为是的问题,然后重新手写了一些配置依然会报错,证明不是的问题。规则真的很严格。配置问题按照的文档默认是,按照说明应该是不会阻止。 问题 项目一开始使用的是create-react-app创建的,配置的ESLint是用的AlloyTeam的eslint-config-alloy/react, 默认配置已经很合理了,并且每条配置都有相应的说明,只需要再根据个人喜好修改一些rule...
阅读 2002·2019-08-30 15:52
阅读 2949·2019-08-29 16:09
阅读 1303·2019-08-28 18:30
阅读 2436·2019-08-26 12:24
阅读 1026·2019-08-26 12:12
阅读 2255·2019-08-26 10:45
阅读 553·2019-08-23 17:52
阅读 757·2019-08-23 16:03