设计模式
单例模式
定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。 单例模式的核心是确保只有一个实例,并提供全局访问。
var Singleton = function(name) {
this.name = name;
this.instance = null;
}
Singleton.prototype.getName = function() {
altert(this.name)
}
Singleton.getInstance = function(name) {
if (!this.instance) {
this.instance = new Singleton(name)
}
return this.instance;
}
var a = Singleton.getInstance('sven1')
var b = Singleton.getInstance('sven2')
// a === b
策略模式
俗话说,条条大陆通罗马,很多时候也有多种途径到达同一个目的地。比如我们要去某个地方旅游,可以坐火车、飞机、大巴
定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
例如计算奖金(根据绩效和基础工资)
const strategies = {
S: (salary) => salary * 4,
A: (salary) => salary * 3,
B: (salary) => salary * 2,
}
// 入参(绩效, 基础工资)
const calculateBonus = (level, salary) => {
return strategies[level](salary)
}
console.log(calculateBonus('S', 20000)) // 80000
console.log(calculateBonus('A', 10000)) // 30000
代理模式
代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问
var Flower = function() {}
var xiaoming = {
sendFlower: function(target) {
var flower = new Flower()
target.receiveFlower(flower);
}
}
var B = {
receiveFlower: function(flower) {
A.receiveFlower(flower)
}
}
var A = {
receiveFlower: function(flower) {
console.log('收到花'+flower)
}
}
xiaoming.sendFlower(B)
var Flower = function() {}
var xiaoming = {
sendFlower: function(target) {
var flower = new Flower()
target.receiveFlower(flower);
}
}
var B = {
receiveFlower: function(flower) {
A.listenGoodMood(function() {
A.receiveFlower(flower)
})
}
}
var A = {
receiveFlower: function(flower) {
console.log('收到花'+flower)
},
listenGoodMood: function(fn) {
settTmeout(function() {
fn()
}, 10000)
}
}
xiaoming.sendFlower(B)
// 保护代理
var Flower = function() {}
var xiaoming = {
sendFlower: function(target) {
target.receiveFlower();
}
}
var B = {
receiveFlower: function(flower) {
A.listenGoodMood(function() {
var flower = new Flower();
A.receiveFlower(flower)
})
}
}
var A = {
receiveFlower: function(flower) {
console.log('收到花'+flower)
},
listenGoodMood: function(fn) {
settTmeout(function() {
fn()
}, 10000)
}
}
xiaoming.sendFlower(B)
var myImage = (funcrion() {
var imgNode = document.createElement('img');
document.body.appendChild(imgNode);
return {
setSrc: function(src) {
imgNode.src = src
}
}
})()
var proxyImage = (function() {
var img = new Image;
img.onload = function() {
myImage.setSrc(this.src);
}
return {
setSrc: function(src) {
myImage.setSrc('/loading.gif')
img.src = src
}
}
})()
proxyImage.setSrc( 'http:// imgcache.qq.com/music/photo/k/000GGDys0yA0Nk.jpg' );
迭代器模式
迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。 内部迭代器:内部已经定义好了迭代规则,它完全接手整个迭代过程,外部只需要一次初始调用 外部迭代器必须显示地请求迭代下一个元素
// 内部迭代器
var each = function(ary, callback) {
for(var i = 0, l = ary.length; i < 1; i++) {
callback.call(ary[i], i, ary[i])
}
}
each([1, 2, 3], function(i n) {
alert([i, n])
})
// 外部迭代器
var Iterator = function(obj) {
var current = 0;
var next = function() {
current += 1
}
var isDone = function() {
return current >= obj.length
}
var getCurrItem = function() {
return obj[current]
}
return {
next: next,
isDone: isDone,
getCurrItem: isCurrItem
}
}
var compare = function(iterator1, iterator2) {
while(!iterator1.isDone && !iterator2.isDone()) {
if(iterator1.getCurrItem() !== iterator2.getCurrItem()) {
throw new Error('iterator1和iterator2不相等')
}
iterator1.next();
iterator2.next();
}
altert('iterator1和iterator2相等')
}
命令模式
命令模式指的是一个执行某些特定事情的指令
var button1 = document.getElementById('button1')
var button2 = document.getElementById('button2')
var button3 = document.getElementById('button3')
var bindClick = function(button, func) {
button.onclick =ffunc;
}
var MenuBar = {
refresh: function() {
console.log('刷新菜单')
}
}
var SubMenu = {
add: funciotn() {
console.log('增加子菜单')
},
del: function() {
console.log('删除子菜单')
}
}
bindClick(button1, MenuBar.refresh)
bindClick(button2, MenuBar.add)
bindClick(button3, MenuBar.del)
适配器模式
适配器模式的作用是解决两个软件实体间的接口不兼容的问题。
var googleMap = {
show: function() {
console.log('谷歌地图')
}
}
var baiduMap = {
display: function() {
console.loog('百度地图')
}
}
var baiduMapAdapter = {
show: baiduMap.display()
}
renderMap(googleMap)
renderMap(baiduMapAdapter)
设计原则和编程技巧
单一职责原则
单一职责原则:一个类应该仅有一个引起它变化的原因 代理模式
// 不用代理
var myImage = (function() {
var imgNode = document.createElement('img');
document.body.appendChild(imgNode)
var img = new Image;
img.onload = function(src) {
setSrc: function(src) {
imgNode.src = '/loading.gif';
img.src = src
}
}
})()
MyImage.setSrc('http:// imgcache.qq.com/music/photo/k/000GGDys0yA0Nk.jpg')
// 代理
// myImage负责往页面中添加img标签
var myImage = (funcrion() {
var imgNode = document.createElement('img');
document.body.appendChild(imgNode);
return {
setSrc: function(src) {
imgNode.src = src
}
}
})()
// proxyImage负责预加载图片,并在预加载完成之后把请求体交给本体myImage
var proxyImage = (function() {
var img = new Image;
img.onload = function() {
myImage.setSrc(this.src);
}
return {
setSrc: function(src) {
myImage.setSrc('/loading.gif')
img.src = src
}
}
})()
proxyImage.setSrc( 'http:// imgcache.qq.com/music/photo/k/000GGDys0yA0Nk.jpg' );
迭代器模式
// 反例
var appendDiv = function(data) {
for(var i = 0, l = data.length; i < l; i ++) {
var div = document.createElement('div');
div.innerHTML = data[i];
document.body.appendChild(div)
}
}
appendDiv([1, 2, 3, 4, 5])
var each = funciton(obj, callback) {
var value,
i = 0,
length = obj.length,
isArray = isArray(obj);
if (isArray) {
for(; i < length; i ++) {
callback.call(obj[i], i, obj[i])
}
} else {
for(i in obj) {
value = callback.call(onj[i], i, obj[i])
}
}
}
var appendDiv = function(data) {
each(data, function(i, n) {
var div = document.createElement('div')
div.innerHTML = n;
document.appendChild(div)
})
}
appendDiv([1, 2, 3, 4, 5])
appendDiv({a: 1, b: 2, c: 3, d: 4, e: 5})
单例模式
// 创建登录浮窗(不用设计模式)
var createLoginLayer = (function() {
var div;
return function() {
if (!div) {
div = document.createElement('div');
div.innerHtml = '我是登录浮窗'
document.body.appendChild(div);
}
return div;
}
})()
// 管理单例的职责和创建登录浮窗的指责分开封装
var getSingle = function(fn) {
var result;
return function() {
return result || (result = fn.apply(this, arguments))
}
}
var createLoginLayer = function() {
div = document.createElement('div');
div.innerHtml = '我是登录浮窗'
document.body.appendChild(div);
return div;
}
var createSingleLoginLayer = getSingle(createLoginLayer)
createSingleLoginLayer();
createSingleLoginLayer();