第一次学习设计模式 repo 所有的代码都在这儿啦!
工厂模式 相关资料:
JavaScript设计模式总结
js设计模式-工厂模式
创建三个角色然后随机决斗⚔️
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 console .log('工厂模式' );const attackPower = () => Math .floor(Math .random() * 100 + 1 )class Warrior { constructor ( ) { this .occupation = '战士' this .skill = '单一狂砍' this .blood = 100 this .hit = attackPower() } } class Mage { constructor ( ) { this .occupation = '法师' this .skill = '集体冰冻' this .blood = 100 this .hit = attackPower() } } class Archer { constructor ( ) { this .occupation = '射手' this .skill = '全局轰炸' this .blood = 100 this .hit = attackPower() } } class RoleFactory { constructor ( ) {} createRole (role ) { let roles = { Warrior: Warrior, Mage: Mage, Archer: Archer } const Character = roles[role] return role ? new Character() : new Warrior() } } let roleFactory = new RoleFactorylet warrior = roleFactory.createRole('Warrior' )let mage = roleFactory.createRole('Mage' )let archer = roleFactory.createRole('Archer' )console .log('warrior:' , warrior);console .log('mage:' , mage);console .log('archer:' , archer);console .log('----------' )const randomRole = (data, number ) => { if (!data || !data.length || !number) return let randomRole = [] for (let i = 0 ; i < data.length; i++) { let sub = Math .floor(Math .random() * data.length ) randomRole.push(...data.splice(sub, 1 )) } return randomRole } const duel = roles => { let maxRole = null let maxHit = -1 roles.map(item => { console .log(item) if (item.hit > maxHit) { maxRole = item maxHit = item.hit } else if (item.hit === maxHit) { maxRole = null maxHit = -1 } }) return maxRole } const compose = (...fn ) => fn.reduce((a, b ) => (...args ) => a(b(...args)))let winner = compose(duel, randomRole)([warrior, mage, archer], 2 )if (winner) { console .log(`胜利者是: ${winner.occupation} , 他的技能是: ${winner.skill} , 攻击力: ${winner.hit} ` ) } else { console .log(`这是平局` ) }
输出
1 2 3 4 5 6 7 8 工厂模式 warrior: Warrior { occupation : '战士' , skill : '单一狂砍' , blood : 100 , hit : 1 } mage: Mage { occupation : '法师' , skill : '集体冰冻' , blood : 100 , hit : 39 } archer: Archer { occupation : '射手' , skill : '全局轰炸' , blood : 100 , hit : 33 } ---------- Warrior { occupation : '战士' , skill : '单一狂砍' , blood : 100 , hit : 1 } Mage { occupation : '法师' , skill : '集体冰冻' , blood : 100 , hit : 39 } 胜利者是: 法师, 他的技能是: 集体冰冻, 攻击力: 39
因为第一次 学习 还不太知道具体的优点和好处 也没办法口喷 所以暂时留个坑给自己 下次更加了解之后回来填坑 🍑
单例模式 https://juejin.im/post/5c984610e51d45656702a785
https://fanerge.github.io/2017/js%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F.html
定义:单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。 – 复制的
我的理解为一个类仅有一个实例, 并且全局访问都是相同的实例
建议先看完上面文章的单例模块, 我觉得他们总结得比我要好
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 const loginBox = (function ( ) { let div return function ( ) { if (!div) { div = document .createElement('div' ) div.onclick = function ( ) { div.style.display = 'none' } div.innerHTML = '登录 hhhh (单击我隐藏)' document .body.appendChild(div) } return div } })() document .querySelector('#btn' ).onclick = function ( ) { let loginbox = loginBox() loginbox.style.display = 'block' }
这只是一个简单的示范… 🍑
装饰器模式 https://juejin.im/post/5c984610e51d45656702a785
在不改变对象自身的基础上,动态的给某个对象添加新的功能,同时又不改变其接口
https://fanerge.github.io/2017/js%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-%E8%A3%85%E9%A5%B0%E8%80%85%E6%A8%A1%E5%BC%8F.html
定义:装饰者(decorator)模式能够在不改变对象自身的基础上,在程序运行期间给对象动态的添加职责。
这样给对象动态的增加职责的方式就没有改变对象自身,一个对象放入另一个对象就形成了一条装饰链(一个聚合对象), 而上面的shot和track也就是装饰者、装饰函数 ,当函数执行时,会把请求转给链中的下一个对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 { class Plane { fire ( ) { console .log('发射普通子弹' ) } } class Missile { plane: any constructor (plane ) { this .plane = plane } fire () { this .plane.fire() console .log('发射导弹' ) } } let plane = new Plane() plane = new Missile(plane) console .log(plane.fire()) }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 { let func = function ( ) { console .log('2' ) } Function .prototype.before = function (fn ) { const _this = this return function ( ) { fn.apply(this , arguments ) return _this.apply(this , arguments ) } } Function .prototype.after = function (fn ) { const _this = this return function ( ) { const ret = _this.apply(this , arguments ) fn.apply(this , arguments ) return ret } } func = func.before(function ( ) { console .log(1 ) }).after(() => { console .log(3 ) }); func() }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 { function func1 ( ) { console .log(1 ) } function func2 ( ) { console .log(2 ) } class Func { @func2 @func1 init ( ) { console .log(3 ) } } let func = new Func() func.init() }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 { const before = function (fn, before ) { return function ( ) { before.apply(this , arguments ) return fn.apply(this , arguments ) } } const after = function (fn, after ) { return function ( ) { const ret = fn.apply(this , arguments ) after.apply(this , arguments ) return ret } } function func (x ) { console .log(x) } function func1 (2 ) { console .log(1 ) } function func2 ( ) { console .log(2 ) } before(func1, func2)() after(func1, func2)() }
核心就在after
before
了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 { function handwashing ( ) { console .log('洗手' ) } function drink ( ) { console .log('喝水' ) } function eat ( ) { console .log('吃饭' ) } before(eat, handwashing)() after(eat, drink)() }
比较基础的演示了 :)
代理模式
为一个对象提供一个代用品或占位符,以便控制对它的访问。
https://fanerge.github.io/2017/js%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 const mult = function ( ) { let a = 1 for (let i = 0 ; i < arguments .length; i++) { a *= arguments [i] } return a } const plus = function ( ) { let a = 0 for (let i = 0 ; i < arguments .length; i++) { a += arguments [i] } return a } const createProxyFactory = function (fn ) { let cache = {} return function ( ) { let args = Array .from(arguments ).join(',' ) if (args in cache) { return cache[args] } else { return cache[args] = fn.apply(this , arguments ) } } } let proxyMult = createProxyFactory(mult)let proxyPlus = createProxyFactory(plus)console .log(proxyMult(1 ,2 ,3 ,4 ))console .log(proxyPlus(1 ,2 ,3 ,4 ))
这里每次进行同类的计算时(乘法和加法两类),先判断缓存对象cache中是否存在该参数连接成的字符串作为key的属性。 如果有,则直接从cache中读取,否则就进行计算并保存其结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 const sleep = time => new Promise (resolve => setTimeout (resolve, time))const imgFunc = (function ( ) { let imgNode = document .createElement('img' ) document .body.appendChild(imgNode) return { setSrc (src ) { imgNode.src = src } } })() const proxyImage = (function ( ) { const img = new Image() img.onload = function ( ) { imgFunc.setSrc(this .src) } return { setSrc (src ) { imgFunc.setSrc('https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=766379944,3048822499&fm=26&gp=0.jpg' ) setTimeout (() => { img.src = src }, 2000 ) } } })() proxyImage.setSrc('http://t8.baidu.com/it/u=1484500186,1503043093&fm=79&app=86&f=JPEG?w=1280&h=853' )
图片懒加载的方式:先通过一张loading图占位,然后通过异步的方式加载图片,等图片加载好了再把完成的图片加载到img标签里面。
策略模式 https://fanerge.github.io/2017/js%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F.html
定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const strategy = { a (salary ) { return salary * 4 }, b (salary ) { return salary * 3 }, c (salary ) { return salary * 2 } } Object .freeze(strategy)const returnMoney = (type, salary ) => { return strategy[type](salary) } console .log(returnMoney('a' , 1000 ))console .log(returnMoney('b' , 3000 ))console .log(returnMoney('c' , 4000 ))
简单的使用
ps: 策略模式指的是定义一系列的算法,把它们一个个封装起来,将不变的部分和变化的部分隔开, 实际就是将算法的使用和实现分离出来;
表单验证
我在原有的code上加了一个方法(错误展示, 比较基础所以很多地方没有考虑到)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <style > .error-msg { color: red; font-size: 14px; } </style > <form id ="registerForm" > <div > <label for ="" > 用户名</label > <input type ="text" name ="username" > </div > <div > <label for ="" > 密码</label > <input type ="password" name ="password" > </div > <div > <label for ="" > 手机号码</label > <input type ="text" name ="phoneNumber" > </div > <button > submit</button > </form >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 const strategyForm = { isNotEmpty (value, errorMsg){ if (value === '' ) { return errorMsg; } }, minLength (value, length, errorMsg){ if (value.length < length) { return errorMsg; } }, mobileFormat (value,errorMsg){ if (!/(^1[3|5|8][0-9]{9}$)/ .test(value)) { return errorMsg; } } }; Object .freeze(strategyForm);const Validator = function ( ) { this .cache = [] } Validator.prototype.add = function (dom, rules ) { let slef = this const addErrorMsg = (msg, dom, errorMsg ) => { if (msg) { let errorMsgDom = dom.parentNode.querySelector('.error-msg' ) if (errorMsgDom) { errorMsgDom.innerHTML = errorMsg } else { let errorHtml = document .createElement('span' ) errorHtml.className = 'error-msg' errorHtml.innerHTML = errorMsg dom.parentNode.appendChild(errorHtml) } } else { let errorMsgDom = dom.parentNode.querySelector('.error-msg' ) if (errorMsgDom) { errorMsgDom.remove() } } } for (let i = 0 , rule; rule = rules[i++]; ) { (function (rule ) { let strategyArr = rule.strategy.split(':' ) let errorMsg = rule.errorMsg slef.cache.push(function ( ) { let strategy = strategyArr.shift() strategyArr.unshift(dom.value) strategyArr.push(errorMsg) let msg = strategyForm[strategy].apply(dom, strategyArr) addErrorMsg(msg, dom, errorMsg) return msg }) })(rule) } } Validator.prototype.start = function ( ) { for (let i = 0 , validatorFunc; validatorFunc = this .cache[i++];) { let msg = validatorFunc() if (msg) return msg } } let registerForm = document .getElementById('registerForm' )let validateFunc = function ( ) { let validator = new Validator() validator.add(registerForm.username, [ { strategy : 'isNotEmpty' , errorMsg : '用户名不能为空' }, { strategy : 'minLength:6' , errorMsg : '用户名长度不能小于6位' } ]) validator.add(registerForm.password,[ {strategy : 'minLength:6' ,errorMsg :'密码长度不能小于6位' }, ]); validator.add(registerForm.phoneNumber,[ {strategy : 'mobileFormat' ,errorMsg :'手机号格式不正确' }, ]); let errorMsg = validator.start() return errorMsg } registerForm.onsubmit = function ( ) { let errorMsg = validateFunc() if (errorMsg) { console .log(errorMsg) } else { console .log('done' ) } return false }
中介者模式 https://fanerge.github.io/2017/js%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-%E4%B8%AD%E4%BB%8B%E8%80%85%E6%A8%A1%E5%BC%8F.html
定义:中介者模式的作用就是解除对象与对象之间的紧耦合关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 let M = {}let V = {}let C = {}M.data = 'Hello World' V.render = (M ) => { document .body.append(document .createElement('p' ).innerHTML = M.data) } C.handleOnload = () => { V.render(M) } window .onload = C.handleOnload
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <form action ="#" id ="selectPhone" > <div > <label for ="" > 选择手机颜色</label > <select name ="" id ="colorSelect" > <option value ="" > 请选择</option > <option value ="red" > 红色</option > <option value ="blue" > 蓝色</option > </select > </div > <div > <label for ="" > 选择内存</label > <select name ="" id ="memorySelect" > <option value ="" > 请选择</option > <option value ="16G" > 16G</option > <option value ="32G" > 32G</option > </select > </div > <div > <label for ="" > 输入购买数量</label > <input type ="number" min ="0" id ="numberInput" > </div > <div > 您选择了颜色: <div id ="colorInfo" > </div > <br /> 您选择了内存: <div id ="memoryInfo" > </div > <br /> 您输入了数量: <div id ="numberInfo" > </div > <br /> <button id ="nextBtn" disabled ="true" > 请选择手机颜色和购买数量</button > </div > </form >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 let goods = { "red|32G" : 3 , "red|16G" : 0 , "blue|32G" : 1 , "blue|16G" : 6 } let colorSelect = document .getElementById( 'colorSelect' )let memorySelect = document .getElementById( 'memorySelect' )let numberInput = document .getElementById( 'numberInput' )let colorInfo = document .getElementById( 'colorInfo' )let memoryInfo = document .getElementById( 'memoryInfo' )let numberInfo = document .getElementById( 'numberInfo' )let nextBtn = document .getElementById( 'nextBtn' )let mediator = (function ( ) { return { changed (obj ) { var color = colorSelect.value let memory = memorySelect.value let number = numberInput.value if (obj === colorSelect) { colorInfo.innerHTML = color } else if (obj === memorySelect) { memoryInfo.innerHTML = memory } else if (obj === numberInput) { numberInfo.innerHTML = number } else { console .log(obj) } if (!color) { nextBtn.disabled = true nextBtn.innerHTML = '请选择手机颜色' return } if (!memory) { nextBtn.disabled = true nextBtn.innerHTML = '请选择内存大小' return } if (((number - 0 ) | 0 !== number - 0 )) { nextBtn.disabled = true nextBtn.innerHTML = '请输入正确的购买数量' return } nextBtn.disabled = false ; nextBtn.innerHTML = '放入购物车' ; } } })() colorSelect.onchange = function ( ) { mediator.changed( this ); }; memorySelect.onchange = function ( ) { mediator.changed( this ); }; numberInput.onchange = function ( ) { mediator.changed( this ); };
发布订阅模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 const Event = (function ( ) { let list = {} const listen = function (key, fn ) { if (!list[key]) { list[key] = [] } list[key].push(fn) } const trigger = function ( ) { let key = Array .prototype.shift.call(arguments ) let fns = list[key] if (!fns || fns.length === 0 ) { return false } for (let i = 0 , fn; fn = fns[i++];) { fn.apply(this , arguments ) } } const remove = function (key, fn ) { let fns = list[key] if (!fns) { return false } if (!fn) { fns && (fns.length = 0 ) } else { for (let i = fns.length - 1 ; i >= 0 ; i--) { let _fn = fns[i] if (_fn === fn) { fns.splice(i, 1 ) } } } } return { listen, trigger, remove } })() function d1 ( ) { console .log('d11111' ) } function d2 ( ) { console .log('d22222' ) } function d3 ( ) { console .log('d33333' ) } Event.listen('color' , d1) Event.listen('color' , d2) Event.listen('color' , d3) Event.listen('size' , d1) Event.listen('size' , d2) Event.remove('size' , d1) Event.listen('size' , d3) Event.trigger('color' ) console .log('----' )Event.trigger('size' ) console .log('----' )Event.trigger('color' )
迭代器模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 const each = (array, callback ) => { for (let i = 0 , len = array.length; i < len; i++) { if (callback.call(array[i], array[i], i) === false ) { break } } } each([1 ,2 ,3 ,4 ,5 ], (val, i ) => { console .log(val + ' - ' + i) }) console .log('-----' )each([1 ,2 ,3 ,4 ,5 ], (val, i ) => { if (i === 3 ) { return false } console .log(val + ' - ' + i) }) const Iterator = obj => { let current = 0 ; const next = () => { if (current > obj.length) { return false } current += 1 ; } const isDone = () => { return current >= obj.length } const getCurrentItem = () => { return obj[current] } return { next, isDone, getCurrentItem } } console .log('-----' )let iterator = Iterator([1 ,2 ,3 ,4 ,5 ])console .log(iterator.getCurrentItem())console .log(iterator.getCurrentItem())iterator.next() console .log(iterator.getCurrentItem())console .log(iterator.isDone())iterator.next() console .log(iterator.getCurrentItem())iterator.next() console .log(iterator.getCurrentItem())iterator.next() console .log(iterator.getCurrentItem())iterator.next() console .log(iterator.getCurrentItem())iterator.next() console .log(iterator.isDone())
桥接模式 https://fanerge.github.io/2017/js%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-%E6%A1%A5%E6%8E%A5%E6%A8%A1%E5%BC%8F.html
定义:桥接模式(Bridge)将抽象部分与它的实现部分分离,使它们都可以独立地变化。
外观模式 1 2 3 4 <button id ="button" > 外观模式</button > <div id ="foo" > </div > <div id ="foo1" > </div > <div id ="foo2" > </div >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 const addEvent = function (el, ev, fn ) { if (el.addEventListener) { el.addEventListener(ev, fn, false ) } else if (el.attachEvent) { el.attachEvent(`on${ev} ` , fn) } else { el[`on${ev} ` ] = fn } } let N = window .N || {}N.tools = { stopPropagation (e ) { if (e.stopPropagation) { e.stopPropagation() } else { e.cancelBubble = true } }, preventDefault (e ) { if (e.preventDefault) { e.preventDefault() } else { e.returnValue = false } }, stopEvent (e ) { this .stopPropagation(e) this .preventDefault(e) } } addEvent(document .getElementById('button' ), 'click' , function ( ) { console .log('button' ) }) function setStyles (elements, styles ) { for (let i = 0 , len = elements.length; i < len; i++) { let element = document .getElementById(elements[i]) if (element) { for (let property in styles) { element.style[property] = styles[property] } } } } setStyles(['foo' , 'foo1' , 'foo2' ], { backgroundColor: 'red' , width: '150px' , height: '200px' });
访问者模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 function Visitor ( ) { this .visit = function (ConceteElement ) { ConceteElement.doSomething() } } function ConceteElement ( ) { this .doSomething = function ( ) { console .log('this is a element' ) } this .accept = function (visitor ) { visitor.visit(this ) } } let visitor = new Visitor()let conceteElement = new ConceteElement()conceteElement.accept(visitor)
模版方法模式 定义:模板方法模式由二部分组成,第一部分是抽象父类,第二部分是具体实现的子类,一般的情况下是抽象父类封装了子类的算法框架,包括实现一些公共方法及封装子类中所有方法的执行顺序,子类可以继承这个父类,并且可以在子类中重写父类的方法,从而实现自己的业务逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 const ITInterview = function ( ) {}ITInterview.prototype.writeTest = function ( ) { console .log('this is a write test' ) } ITInterview.prototype.technicalInterView = function ( ) { console .log('this is a technical interview' ) } ITInterview.prototype.leader = function ( ) { console .log('this is a leader interview' ) } ITInterview.prototype.waitNotice = function ( ) { console .log('wait notice' ) } ITInterview.prototype.init = function ( ) { this .writeTest() this .technicalInterView() this .leader() this .waitNotice() } const itInterview = new ITInterview()itInterview.init() const BaiDuITInterview = function ( ) {}BaiDuITInterview.prototype = new ITInterview() BaiDuITInterview.prototype.writeTest = function ( ) { console .log('this is a baidu write test' ) } BaiDuITInterview.prototype.technicalInterView = function ( ) { console .log('this is a baidu technical interview' ) } const baiduItInterview = new BaiDuITInterview()baiduItInterview.init()
组合模式 定义:组合模式(Composite)将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 let Folder = function (name ) { this .name = name this .files = [] } Folder.prototype.add = function (file ) { this .files.push(file) } Folder.prototype.scan = function ( ) { console .log('开始文件扫描:' + this .name) for ( let i = 0 , file, files = this .files; file = files[i++]; ) { file.scan(); } } let File = function (name ) { this .name = name } File.prototype.add = function ( ) { throw new Error ('文件下面不能再添加文件' ) } File.prototype.scan = function ( ) { console .log('开始扫瞄:' + this .name) } let folder = new Folder('前端学习' );let folder1 = new Folder('JS学习' );let folder2 = new Folder('JQ学习' );let file1 = new File('JS设计模式' );let file2 = new File('JQ实战' );let file3 = new File('前端性能' );folder1.add(file1); folder2.add(file2); folder.add(folder1); folder.add(folder2); folder.add(file3); folder.scan();
备忘录模式 定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 const render = data => { console .log(data) } const page = function ( ) { let cache = {} return (page ) => { console .log('page' , page) console .log('cache' , JSON .stringify(cache)) if (cache[page]) { render(cache[page]) } else { let data = [ { title: "hi" } ] cache[page] = data render(data) } } }() page(1 ) page(1 ) page(1 ) page(1 ) page(1 ) page(2 ) page(3 ) page(4 ) page(2 )
职责链模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 var order500 = function (orderType, pay, stock ) { if (orderType === 1 && pay) { console .log('500 rmb deposit, get 100 coupon ' ) } else { return 'nextSuccessor' } }; var order200 = function (orderType, pay, stock ) { if (orderType === 2 && pay) { console .log('200 rmb deposit , get 50 coupon' ) } else { return 'nextSuccessor' ; } }; var orderNormal = function (orderType, pay, stock ) { if (stock > 0 ) { console .log('normal buy no coupon' ) } else { console .log('the stock lack' ) } }; let Chain = function (fn ) { this .fn = fn this .successor = null } Chain.prototype.setNextSuccessor = function (successor ) { return this .successor = successor } Chain.prototype.passRequest = function ( ) { let ret = this .fn.apply(this , arguments ) if (ret === 'nextSuccessor' ) { return this .successor && this .successor.passRequest.apply(this .successor, arguments ) } return ret } var chainOrder500 = new Chain(order500);var chainOrder200 = new Chain(order200);var chainOrderNormal = new Chain(orderNormal);chainOrder500.setNextSuccessor(chainOrder200) chainOrder200.setNextSuccessor(chainOrderNormal) chainOrder500.passRequest(1 ,true ,6 ); chainOrder500.passRequest(2 ,true ,4 ); chainOrderNormal.passRequest(2 ,true ,0 );
状态模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 var trafficLight = (function ( ) { var currentLight = null ; return { change: function (light ) { currentLight = light; currentLight.go(); } } })(); function RedLight ( ) { }RedLight.prototype.go = function ( ) { console .log("this is red light" ); } function GreenLight ( ) { }GreenLight.prototype.go = function ( ) { console .log("this is green light" ); } function YellowLight ( ) { }YellowLight.prototype.go = function ( ) { console .log("this is yellow light" ); } trafficLight.change(new RedLight()); trafficLight.change(new YellowLight()); function Menu ( ) { }Menu.prototype.toggle = function (state ) { state(); } var menuStates = { "show" : function ( ) { console .log("the menu is showing" ); }, "hide" : function ( ) { console .log("the menu is hiding" ); } }; var menu = new Menu();menu.toggle(menuStates.show); menu.toggle(menuStates.hide);
享元模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 var Model = function (sex ) { this .sex = sex; } Model.prototype.takePhoto = function ( ) { console .log('sex=' + this .sex + 'underwear=' + this .underwear ) } var maleModel = new Model('male' );let female = new Model('female' ); for (var i = 1 ; i <=50 ; i++){ maleModel.underwear = 'underwear' + i; maleModel.takePhoto(); } for (var i = 1 ; i <=50 ; i++){ female.underwear = 'underwear' + i; female.takePhoto(); } let toolTipFactory = (function ( ) { let tooplTipPool = [] return { create: function ( ) { if (tooplTipPool.length === 0 ) { console .log(1 ) let div = document .createElement('div' ) document .body.appendChild(div) return div } else { console .log(2 ) return tooplTipPool.shift() } }, recover: function (tooltipDOm ) { tooplTipPool.push(tooltipDOm) } } })() let arr = []for (let i = 0 , str; str = ['a' , 'b' ][i++];) { let toolTip = toolTipFactory.create() toolTip.innerHTML = str arr.push(toolTip) } for (let i = 0 , toolTip; toolTip = arr[i++];) { toolTipFactory.recover(toolTip) } for (let i = 0 , str; str = ['a' , 'b' , 'c' , 'd' , 'e' , 'f' ][i++];) { let toolTip = toolTipFactory.create() toolTip.innerHTML = str }