Last active
August 29, 2015 14:14
-
-
Save mizhdi/28769a52c2aea08baf31 to your computer and use it in GitHub Desktop.
javascript patterns
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 外观模式 | |
// | |
// 外观模式是一种很简单的模式,它只是为对象提供了更多的可供选择的接口。 | |
// 使方法保持短小而不是处理太多的工作是一种很好的实践。 | |
// 在这种实践的指导下,你会有一大堆的方法,而不是一个有着非常多参数的uber方法。 | |
// 有些时候,两个或者更多的方法会经常被一起调用。 | |
// 在这种情况下,创建另一个将这些重复调用包裹起来的方法就变得意义了。 | |
var myevent = { | |
// …… | |
stop: function (e) { | |
e.preventDefault(); | |
e.stopPropagation(); | |
} | |
// …… | |
}; | |
// 策略模式 | |
// 策略模式允许在运行的时候选择算法。 | |
// 你的代码的使用者可以在处理特定任务的时候根据即将要做的事情的上下文来从一些可用的算法中选择一个。 | |
// 使用策略模式的一个例子是解决表单验证的问题。 | |
// 你可以创建一个validator对象,有一个validate()方法。 | |
// 这个方法被调用时不用区分具体的表单类型,它总是会返回同样的结果——一个没有通过验证的列表和错误信息。 | |
// 但是根据具体的需要验证的表单和数据,你代码的使用者可以选择进行不同类别的检查。 | |
// 你的validator选择最佳的策略来处理这个任务,然后将具体的数据检查工作交给合适的算法去做。 | |
// 验证数据 | |
var data = { | |
first_name: 'supre', | |
last_name: 'man', | |
age: 'unknow', | |
username: '0_o' | |
} | |
validator.config = { | |
first_name: 'isNonEmpty', | |
age: 'isNumber', | |
username: 'isAlphaNum' | |
} | |
validator.validate(data); | |
if (validator.hasErrors) { | |
console.log(validator.messages.join('\n')); | |
} | |
var validator = { | |
types: { | |
isNonEmpty: { | |
validate: function(value) { | |
return value !== ''; | |
}, | |
instructions: 'the value cannot be empty!' | |
}, | |
isNumber: { | |
validate: function(value) { | |
return !isNaN(value); | |
}, | |
instructions: "the value can only be a valid number, e.g. 1, 3.14 or 2010" | |
}, | |
isAlphaNum: { | |
validate: function(value) { | |
return !/[^a-z0-9]/i.test(value); | |
}, | |
instructions: "the value can only contain characters and numbers, no special symbols" | |
} | |
}, | |
messages: [], | |
config: { | |
first_name: 'isNonEmpty', | |
age: 'isNumber', | |
username: 'isAlphaNum' | |
}, | |
validate: function(data) { | |
this.messages = []; | |
for (i in data) { | |
if data.hasOwnProperty(i) { | |
var type = this.config[i]; | |
var checker = this.types[type]; | |
if (!type) { | |
continue; | |
} | |
if (!checker) { | |
throw { | |
name: 'ValidtionError', | |
messages: 'No handle to validate type ' + type | |
}; | |
} | |
var result_ok = checker.validate(data[i]); | |
if (!result_ok) { | |
msg = "Invalid value for *" + i + "*, " + checker.instructions; | |
this.messages.push(msg); | |
} | |
} | |
} | |
reutrn this.hasErrors(); | |
}, | |
hasErrors: function() { | |
return this.messages.length !== 0; | |
} | |
}; | |
// 遍历模式 | |
var element; | |
while (element = agg.next()) { | |
// 访问element…… | |
console.log(element); | |
} | |
while (agg.hasNext()) { | |
// 访问element…… | |
console.log(agg.next()); | |
} | |
// 工厂模式 | |
// 使用工厂模式的目的就是创建对象。它通常被在类或者类的静态方法中实现,目的是: | |
// 执行在建立相似的对象时进行的一些重复操作 | |
// 让工厂的使用者在编译阶段创建对象时不必知道它的特定类型(类) | |
// 第二点在静态的基于类的语言中更重要,因为在(编译阶段)提前不知道类的情况下, | |
// 创建类的实例是一件多少有些特殊的行为。但在JavaScript中, | |
// 这部分的实现却是相当容易的事情。 | |
function CarMaker() {} | |
CarMaker.prototype.drive = function() { | |
return 'Vroom, I have ' + this.doors + ' doors'; | |
}; | |
CarMaker.factory = function(type) { | |
var constr = type, newcar; | |
if (typeof CarMaker[consrt] !== 'function') { | |
throw { | |
name: 'Error', | |
message: constr + " doesn't exist"; | |
} | |
if (typeof CarMaker[constr].prototype.drive !== "function") { | |
CarMaker[constr].prototype = new CarMaker(); | |
} | |
// 创建一个新实例 | |
newcar = new CarMaker[constr](); | |
// 这里可以选择性地调用一些方法,然后返回实例 | |
return newcar; | |
} | |
}; | |
// 创建特定类型的构造函数 | |
CarMaker.Compact = function () { | |
this.doors = 4; | |
}; | |
CarMaker.Convertible = function () { | |
this.doors = 2; | |
}; | |
CarMaker.SUV = function () { | |
this.doors = 24; | |
}; | |
// 装饰模式 | |
function Sale(price) { | |
this.price = price || 100; | |
} | |
Sale.prototype.getPrice = function () { | |
return this.price; | |
}; | |
Sale.decorators.fedtax = { | |
getPrice: function () { | |
var price = this.uber.getPrice(); | |
price += price * 5 / 100; | |
return price; | |
} | |
}; | |
Sale.prototype.decorate = function(decorator) { | |
var F = function() {}, | |
overrides = this.constructor.decorators[decorator], | |
i, newobj; | |
F.prototype = this; | |
newobj = new F(); | |
newobj.uber = F.prototype; | |
for (i in overrides) { | |
if (overrides.hasOwnProperty(i)) { | |
newobj[i] = overrides[i]; | |
} | |
} | |
return newobj; | |
}; | |
// 代理模式 | |
var proxy = { | |
ids: [], | |
delay: 50, | |
timeout: null, | |
callback: null, | |
context: null, | |
makeRequest: function(id, callback, context) { | |
this.ids.push(id); | |
this.callback = callback; | |
this.context = context; | |
if (!this.timeout) { | |
this.timeout = setTimeout(function() { | |
proxy.flush(); | |
}, this.delay); | |
} | |
}, | |
flush: function() { | |
http.makeRequest(this.ids, 'proxy.handler'); | |
this.timeout = null; | |
this.ids = []; | |
}, | |
handler: function(data) { | |
var i max; | |
// 单个视频 | |
if (parseInt(data.query.count, 10) === 1) { | |
proxy.callback.call(proxy.context, data.query.results.Video); | |
return; | |
} | |
// 多个视频 | |
for (i = 0, max = data.query.results.Video.length; i < max; i += 1) { | |
proxy.callback.call(proxy.context, data.query.results.Video[i]); | |
} | |
} | |
} | |
// 中介者模式 | |
// 中介者模式就是一个缓解此问题的办法,它通过解耦来提升代码的可维护性。 | |
// 在这个模式中,各个彼此合作的对象并不直接通讯,而是通过一个mediator(中介者)对象通讯。 | |
// 当一个对象改变了状态后,它就通知中介者,然后中介者再将这个改变告知给其它应该知道这个变化的对象。 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment