如何去设计你的功能
设计思路:
需求 => 思考实现需求需要做什么 => 设计有哪些模块 => 整体类怎么设计 => 思考以后更改的可能,重新设计模块(扩展性) => 编写模块,思考提高代码的健壮性、可读性、有无重复代码(复用性)。
// 栗子1 function Factory(type) { switch(type) { case ‘type1’: return new Type1(); case ‘type2’: return new Type2(); case ‘type3’: return new Type3(); default: return Type(); } }
// 栗子2 jQuery (function() { let jQuery = function(selector) { // return new jQuery(); // 会发生死循环 return new jQuery.fn.init(selector); }
// 吧真正要创建的对象,放到原型链上,或者静态属性上。 // 防止直接调用时发生死循环 jQuery.fn = { init: function() {} };
window.$ = jQuery; })();
<a name="VpwQ6"></a>## 建造者模式应用场景:精细化的构建一个类。<br />把一个复杂的类的各个部分,拆分成独立的类,然后再在最终类里组合到一块。```javascript// 栗子1// 模块1function Model1() {}// 模块2function Model2() {}// 最终的使用类function Final() {this.model1 = new Model1();this.model2 = new Model2();}// 栗子2 vue2源码function Vue(optins) {if (!(this instanceof Vue)) {warn(`Vue is a constructor and shuld be called with the 'new' keyword`);} else {this._init(options);}}// 代码组合 mixininitMixin(Vue); // 初始化混合stateMixin(Vue); // 状态混合eventsMixin(Vue); // 时间系统混合lifecycleMixin(Vue); // 生命周期混合renderMixin(Vue); // 渲染系统混合
单例模式
保证一个类全局只有一个实例化对象。
应用场景:
- 路由
- vuex
- redux ```javascript
// 栗子1 function class1() { if (class1.instance) { return class1.instance; } else { this.a = 1; // class1.instance = new class1(); class1.instance = this; } }
class1.instance = null;
// 栗子2 - vue-router let _vue;
function install(vue) { if (install.installed && _vue === vue) { return; }
install.installed = true; _vue = vue; }
// 在 vue.use 中调用 vue.use();
<a name="UuqBx"></a># 结构型帮助我们优雅的设计代码结构。<a name="mZTv7"></a>## 策略模式优化if-else分支<br />新建一个策略对象,将判断分支当成一个一个的策略。<a name="VmLU0"></a>## 状态模式当if-else分支过多时。<br />封装状态。```javascriptfunction moveDiv() {this.status = [];this.strage = {top: function() {},left: function() {},right: function() {},bottom: function() {},};}moveDiv.prototype.run = function() {this.status = Array.prototype.slice.call(arguments);this.status.forEach(action => {this.strage[action]();});};let moveObj = new moveDiv();moveObj.run('left'); // status == ['left']moveObj.run('left', 'top'); // status == ['left', 'top']
行为型
观察者模式
目的:减少对象间的耦合,提高扩展性。
场景:当两个模块直接沟通会增加他们的耦合性时,不好直接调用,这时使用观察者模式解耦。
栗子:
- 点击事件
- 异步模块 ```javascript
// function observe() { this.message = {}; }
observe.prototype.regist = function(type, fn) { this.message[type] = fn; };
observe.prototype.fire = function(type) { this.messagetype; };
// 转盘 // 初始化HTML模块,转动控制,转动动画,结果模块 let _domArr = []; let _observe = new observe();
// 初始化HTML function htmlInit() { for (let i = 0; i < 10; i++) { let _div = document.createElement(‘div’); _div.setAttribute(‘class’, ‘item’); _domArr.push(_div); } }
// 转动动画 // moveConfig: { moveTime: 0, speed: 1000, } function move(moveConfig) { let nowIn = 0; let removeNum = 9; let timer = setInterval(() => { if (nowIn !== 0) { removeNum = nowIn - 1 }
_domArr[removeNum].setAttribute('class', 'item');_domArr[nowIn].setAttribute('class', 'item item-on');nowIn++;if (nowIn === moveConfig.moveTime) {clearInterval(timer);_observe.fire('finish');}
}, moveConfig.speed); }
// 转动控制 function moveController() { let final = getFinal(); let _circle = Math.floor(final / 10, 0); let _runCircle = 0; let stopNum = final % 10; let _speed = 200;
move({ moveTime: 10, speed: _speed, });
object.regist(‘finish’, function() { let _time = 0; _speed -= 50; if (_runCircle <= _circle) { _time = 10; } else { _time = stopNum; }
move({moveTime: _time,speed: _speed,});
}); }
// 结果模块 function getFinal() { let _num = Math.random() * 10 + 40; return Math.floor(_num, 0); }
<a name="WPeFM"></a># 技巧型帮助我们优化代码的技巧。<a name="5ANTz"></a>## 装饰者模式目的:不重写方法的扩展方法。<br />场景:当一个方法需要扩展,按时又不能修改原方法。<br />三步走:提取原方法,调用原方法,加入新方法。<br />在不入侵老代码的前提下,修改老代码的实现。<br />栗子:1. 代码是以前的老代码。1. 要修改的方法是第三方库的方法。1. 方法时原生方法。```javascript// dom 绑定的事件,只有操作,没有提示。function decorator(dom, fn) {if (typeof dom.onclick === 'function') {let _old = dom.onclick;dom.onclick = function() {_old.call(this);fn.call(this);}}}// 为删除按钮扩展新方法decorator(deleteDom, function() {alert('删除成功!');});// vue -----------------------// 数组的改变触发渲染let arr = ['push', 'pop', 'shift'];let arrayPrototype = Array.prototype;let arrayCopy = Object.create(arrayPrototype);arr.forEach(methods => {arrayCopy[methods] = function() {let _old = arrayPrototype[methods];_old.apply(this, argumennts);// Vue 中触发数据绑定dep.notify();}});
享元模式
把不同部分作为一个享元提取。
目的:减少对象/代码数量
场景:当代码中创建了大量类似对象和类似的代码块
$.extend({a: 1});$.extend({a: 1}, {b: 2});// 普通实现,有重复代码$.extend = function() {if (arguments.length === 1) {for (let item in arguments[0]) {this[item] = arguments[0][item];}} else if (arguments.length === 2) {for (let item in arguments[1]) {arguments[0][item] = arguments[1][item];}}}// 享元模式$.extend = function() {let source = arguments[0];let target = this;if (arguments.length === 2) {source = arguments[1];target = arguments[0];}for (let item in source) {target[item] = source[item];}}
