提高复用性的目的
- 遵循DRY原则(Don't Repeat Yourself)
- 减少代码量,节省开销
什么是好的复用
- 对象可以重复使用,不用修改
- 重复代码少
- 模块功能单一(低耦合)
减少代码数量,高效复用代码的设计模式
- 桥接模式
- 目的:通过桥接代替耦合。
- 应用场景:减少模块之间的耦合。
- 享元模式
- 目的:减少对象/代码数量。
- 应用场景:当代码中创建了大量类似的对象和类似的代码块。
- 要点:保留公用的代码逻辑,将需要改变的代码抽取成公共享元,通过参数来控制。
- 模板方法模式
- 目的:定义一系列操作的骨架,简化后面类似操作的内容。
- 应用场景:当项目中出现很多类似操作内容。
基本结构示例
享元模式的基本结构
function pop() {}
pop.prototype.action = function() {}
pop.prototype.show = function(config) {
const text = config.text || '';
const color = config.text || 'green';
}
const arr = [
{
text: '文本1',
color: 'green',
},
{
text: '文本2',
color: 'red',
}
];
const popup = new pop();
arr.forEach((item) => {
popup.show(item)
});
桥接模式的基本结构
function showColor(color) {}
function rect(color) {
showColor(color);
}
function circle(color) {
showColor(color);
}
function delta(color) {
showColor(color);
}
new circle('green');
模板方法模式的基本结构
function baseNav() {
}
function isFunction(fn) {
return Object.prototype.toString.call(fn).toLocaleLowerCase() === '[object function]';
}
baseNav.prototype.action = function(fn) {
if (isFunction(fn)) {
fn();
return;
}
}
享元模式的应用示例
function uploader(){}
uploader.prototype.init = function(){
}
uploader.prototype.delete = function(){
}
uploader.prototype.uploading = function(filetype,file){
}
var data=[
{
type: 'img',
file: fileob1,
},
{
type: 'txt',
file: fileob2,
},
];
const uploader = new uploader();
for(let i = 0; i < data.length; i++){
uploader.uploading(data[i].type, data[i].file);
};
桥接模式的示例
function menuItem(word, color) {
this.word = word;
this.dom = document.createElement('div');
this.dom.innerHTML = this.word;
this.color = color;
}
function menuColor(colorover, colorout) {
this.colorover = colorover;
this.colorout = colorout;
}
menuItem.prototype.bind = function() {
var self = this;
this.dom.onmouseover = function() {
console.log(self.color);
this.style.color = self.color.colorover;
}
this.dom.onmouseout = function() {
this.style.color = self.color.colorout;
}
}
const data=[
{
word: 'menu1',
color: ['red', 'black']
},
{
word: 'menu2',
color: ['green', 'black']
},
];
for(let i = 0; i < data.length; i++) {
new menuItem(data[i].word, new menuColor(data[i].color[0], data[i].color[1])).bind();
}
const methods=['get', 'post', 'delete', 'put'];
methods.forEach(function(method) {
app[method] = function() {
route[method].apply(route, slice.call(arguments, 1));
}
});
模板方法模式的示例
function basePop(word, size) {
this.word = word;
this.size = size;
this.dom = null;
}
basePop.prototype.init = function() {
const div = document.createElement('div');
div.innerHTML = this.word;
div.style.width = `${this.size.width}px`;
div.style.height = `${this.size.height}px`;
this.dom = div;
}
basePop.prototype.hidden = function() {
this.dom.style.display = 'none';
}
basePop.prototype.confirm = function() {
this.dom.style.display = 'none';
}
function ajaxPop(word, size) {
basePop.call(this, word, size);
}
ajaxPop.prototype = new basePop();
var hidden = ajaxPop.prototype.hidden;
ajaxPop.prototype.hidden = function() {
hidden.call(this);
console.log(1);
}
var confirm = ajaxPop.prototype.confirm;
ajaxPop.prototype.confirm = function() {
confirm.call(this);
$.ajax();
}
function counter() {
this.beforeCounter = [];
this.afterCounter = [];
}
counter.prototype.addBefore = function(fn) {
this.beforeCounter.push(fn);
}
counter.prototype.addAfter = function(fn) {
this.afterCounter.push(fn);
}
counter.prototype.count = function() {
function baseCount(num) {
num += 4;
num *= 4;
return num;
}
var _resultNum = num;
var _arr = [baseCount];
_arr = this.beforeCounter.concat(_arr);
_arr = _arr.concat(this.afterCounter);
while(_arr.length > 0) {
_resultNum = _arr.shift()(_resultNum);
}
return _resultNum;
}
var countObject = new counter();
countObject.addBefore(() => {
num--;
return num;
});
countObject.addAfter(() => {
num *= 2;
return num;
});
countObject.count(10);
JavaScript的组合与继承
- 组合
- JavaScript最初没有专门的继承,所以最初JavaScript推崇函数式的编程,
然后进行统一组合桥接到一起。
- 桥接模式可以看出组合的一种体现,组合的好处是耦合低,方便方法复用,方便扩展。
- 继承
- 在ES6出现class和extend,继承的方式多种多样,但是都是各有弊端。
- 模板方法模式可以看出继承的一种体现,继承的好处是可以自动获得父类的内容与接口,
方便统一化
- 最佳实践
小结
- 桥接模式
- 通过独立方法间的桥接来形成整体功能,这样每个方法都可以被高度复用。
- 享元模式
- 提取出公有部分与私有部分,私有部分作为外部数据传入。从而减少对象数量。
- 模板方法模式
- 当一个功能朝着多样化发展,不妨先定义一个基础的方法,把具体实现延迟到后面。