策略模式

在选择最佳策略以处理特定任务(上下文)的时候仍然保持相同的接口;

//表单验证的例子
var data = {
firs_name: "Super",
last_name: "Man",
age: "unknown",
username: "o_0"
} validator = {
types: {},
message: [],
config: {},
validate: function(data) {
var i, msg, type, checker, result_ok;
this.message = [];
for(i in data) {
if(data.hasOwnProperty(i)) {
type = this.config[i];
checker = this.types[type];
if(!type) continue;
if(!checker) {
throw {
name: "ValidationError",
message: "No handler to validate type " + type
};
}
result_ok = checker.validate(data[i]);
if(!result_ok) {
msg = "Invalid value for *" + i + "*, " + checker.instructions;
this.message.push(msg);
}
}
}
return this.hasErrors();
},
//帮助程序
hasErrors: function() {
return this.message.length !== 0;
}
} validator.config = {
firs_name: 'isNonEmpty',
age: 'isNumber',
username: 'isAlphaNum'
} validator.types = {
isNonEmpty: {
validate: function (value) {
return value !== "";
},
instructions: "this 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 number, no special symbols"
}
} validator.validate(data); if(validator.hasErrors()) {
console.log(validator.message.join('\n'));
}

外观模式

通过把常用方法包装到一个新的方法中,从而提供一个更为便利的API

//以处理浏览器事件为例
var myevent = {
//...
stop: function(e) {
(typeof e.preventDefault === 'function') && e.preventDefault();
(typeof e.stopPropagation === 'function') && e.stopPropagation();
//ie
(typeof e.returnVlaue === 'boolean') && (e.returnVlaue = false);
(typeof e.cancelBubble === 'boolean') && (e.cancelBubble = true);
}
}

代理模式

通过包装一个对象以控制对它的访问,其主要方法是将访问聚集为组成或仅当真正必要的时候才执行访问,从而避免了高昂的操作开销

这种模式的其中一个例子为:延迟初始化;假设初始化对象开销非常大,但客户端可能在初始化对象后从未使用它,这种时候就可以通过代理替换本体对象的接口来解决

  • 首先由客户端发出一个初始化请求,然后代理以一切正常作为响应
  • 但实际上却没有将该消息传递到本体对象;
  • 直到客户端明显需要本体对象完成一些工作的时候,代理财经两个消息一起传递;
//视频列表例子
<p><span id="toggle-all">Toggle Checked</span></p>
<ol id="vids">
<li><input type="checkbox" checked><a href="http://new.music.yahoo.com/vides/--2158073">Gravedigger</a></li>
<li><input type="checkbox" checked><a href="http://new.music.yahoo.com/vides/--4472739">Save Me</a></li>
<li><input type="checkbox" checked><a href="http://new.music.yahoo.com/vides/--45286339">Grush</a></li>
<li><input type="checkbox" checked><a href="http://new.music.yahoo.com/vides/--2144530">Don't Drink The Water</a></li>
<li><input type="checkbox" checked><a href="http://new.music.yahoo.com/vides/--217241800">Funny the Way It Is</a></li>
<li><input type="checkbox" checked><a href="http://new.music.yahoo.com/vides/--2144532">What Would You Say</a></li>
</ol>
//未使用代理
var http = {
makeRequest: function(ids, callback) {
var url = 'http://query.yahooapis.com/v1/public/yql?q=',
sql = 'select * from music.video.id where ids IN ("%ID%")',
format = "format=json",
handler = "callback=" + callback,
script = document.createElement('script')
sql = sql.replace("%ID%", ids.join('","'));
sql = encodeURIComponent(sql);
url += sql + '&' + format + '&' + handler;
script.src = url;
document.body.appendChild(script);
}
}
var videos = {
getPlayer: function(id) {},
updateList: function(data) {},
//展开折叠信息区域
getInfo: function(id) {
var info = $("info" + id);
if(!info) {
//负责与服务器通信
http.makeRequest([id], "videos.updateList");
return;
}
if(info.style.display === "none") {
info.style.display = '';
} else {
info.style.display = 'none';
}
}
}; var $ = function (id) {
return document.getElementById(id);
};
$("vids").onclick = function(e) {
var scr ,id;
e = e || window.event;
src = e.target || e.srcElement;
//阻止跳转
if(src.nodeName !== "A") return;
if(typeof e.preventDefault === "function") e.preventDefault();
e.returnValue = false;
id = src.href.split('--')[1];
//如果是正在播放,即已经展开
if(src.className == "play") {
src.parentNode.innerHTML = videos.getPlayer(id);
return;
}
src.parentNode.id = "v" + id;
videos.getInfo(id);
}; $("toggle-all").onclick = function(e) {
var hrefs, i, max, id;
hrefs = $('vids').getElementsByTagName('a');
for(i = 0, max = hrefs.length; i < max; i += 1) {
if(hrefs[i].className === "play") continue;
if(!hrefs[i].parentNode.firstChild.checked) continue;
id = hrefs[i].href.split('--')[1];
hrefs[i].parentNode.id = '\/' + id;
videos.getInfo(id);
}
}
//使用代理:就只是将http.makeRequest()改为proxy.makeRequest(); var proxy = {
ids: [],
delay: 50,
timeout: null,
callback: null,
context: null,
makeRequest: function(id, callback, context) {
//加入列队
this.ids.push(id);
this.callback = callback || function(){};
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(data.error) return;
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++) {
proxy.callback.call(proxy.context, data.query.results.Video[i]);
}
}
}

缓存代理

代理可以通过将以前的请求结果缓存到新的cache属性中,从而更进一步地保护本体对象http地访问;那么如果videos对象恰好再一次请求同一个视频id,proxy可以直接从缓存中取出该信息

中介者模式

通过使对象之间相互并不直接‘通话’,而是仅通过一个中介者对象进行通信,从而促进形成松散耦合

<p>Player one press "1", player two press "0". Go! (you have half a minute...)</p>
<div id="results"></div>
//
//玩家
function Player(name) {
this.points = 0;
this.name = name;
}
Player.prototype.play = function () {
this.points += 1;
//中介者的played方法在play调用后,更新score哈希表并传送到记分板
mediator.played();
};
//记分板
var scoreboard = {
element: document.getElementById('results'),
update: function (score) {
var i, msg = '';
for (i in score) {
if (score.hasOwnProperty(i)) {
msg += '<p><strong>' + i + '<\/strong>: ';
msg += score[i];
msg += '<\/p>';
}
}
this.element.innerHTML = msg;
}
};
//中介者
var mediator = {
players: {},
setup: function () {
var players = this.players;
players.home = new Player('Home');
players.guest = new Player('Guest');
},
played: function () {
var players = this.players,
score = {
Home: players.home.points,
Guest: players.guest.points
};
scoreboard.update(score);
},
keypress: function (e) {
e = e || window.event; // IE
if (e.which === 49) { // key "1"
mediator.players.home.play();
return;
}
if (e.which === 48) { // key "0"
mediator.players.guest.play();
return;
}
}
};
//初始化中介者
mediator.setup();
window.onkeypress = mediator.keypress;
//30s
setTimeout(function () {
window.onkeypress = null;
alert('Game over!');
}, 30000);

其中记分板与玩家对象并不关联,通过中介者沟通

javascript优化--11模式(设计模式)02的更多相关文章

  1. javascript优化--10模式(设计模式)01

    单体模式:保证一个特定类仅有一个实例;即第二次使用同一个类创建新对象时,应该得到与第一个所创建对象完全相同对象: 在JS中,可以认为每次在使用对象字面量创建对象的时候,实际上就在创建一个单体: 当使用 ...

  2. javascript优化--07模式(对象)02

    沙箱模式: 解决空间命名模式的几个缺点: 命名空间模式中无法同时使用一个应用程序或库的两个版本运行在同一个页面中,因为两者需要相同的全局符号: 以点分割,需要输入更长的字符,解析时间也更长: 全局构造 ...

  3. javascript优化--12模式(设计模式)03

    观察者模式 通过创建一个可观察的对象,当发生一个感兴趣的事件时将该事件通告给所有观察者,从而形成松散的耦合 订阅杂志 //发布者对象 var publisher = { subscribers: { ...

  4. javascript优化--09模式(代码复用)02

    原型继承 ://现代无类继承模式 基本代码: var parent = { name : "Papa" } var child = object(parent); function ...

  5. javascript优化--13模式1(DOM和浏览器模式)

    注意分离: 通过将CSS关闭来测试页面是否仍然可用,内容是否依然可读: 将JavaScript关闭来测试页面仍然可以执行正常功能:所有连接是否正常工作:所有的表单是否可以正常工作: 不使用内联处理器( ...

  6. javascript优化--08模式(代码复用)01

    优先使用对象组合,而不是类继承: 类式继承:通过构造函数Child()来获取来自于另一个构造函数Parent()的属性: 默认模式:子类的原型指向父类的一个实例 function inherit(C, ...

  7. javascript优化--06模式(对象)01

    命名空间: 优点:可以解决命名混乱和第三方冲突: 缺点:长嵌套导致更长的查询时间:更多的字符: 通用命名空间函数: var MYAPP = MYAPP || {}; MYAPP.namespace = ...

  8. javascript优化--05模式(函数)

    回调函数模式: 基本例子: var findNodes = function (callback) { ...................... if (typeof callback !== ' ...

  9. javascript优化--14模式2(DOM和浏览器模式)

    远程脚本 XMLHttpRequest JSONP 和XHR不同,它不受同域的限制: JSONP请求的可以是任意的文档: 请求的URL通常格式为http://example.js?calback=Ca ...

随机推荐

  1. suse linux 命令

    1.修改vftpd配置文件   vi /etc/vsftpd .conf                       #listen=YES   vi /etc/xinetd.d/vsftpd     ...

  2. 【leetcode】Plus One (easy)

    Given a non-negative number represented as an array of digits, plus one to the number. The digits ar ...

  3. 【python】利用pathlib遍历目录Path().rglob

    来源:https://docs.python.org/3/library/pathlib.html 可以用pathlib模块中的Path().rglob来递归遍历文件 from pathlib imp ...

  4. SQL常用命令整理

    1.增加字段 alter table docdsp     add dspcodechar(200)2.删除字段     ALTER TABLE table_NAME DROP COLUMNcolum ...

  5. sql语句按照汉字拼音首字母排序

    oracle : 在oracle9i中新增了按照拼音.部首.笔画排序功能.设置NLS_SORT值SCHINESE_RADICAL_M 按照部首(第一顺序).笔划(第二顺序)排序SCHINESE_STR ...

  6. IOS-Gesture(手势识别)

    手势识别——Gesture Recognizer •iOS3.2版本之后,苹果推出了手势识别(Gesture Recognizer),其目的是: –简化开发者的开发难度 –统一用户体验 • •iOS目 ...

  7. August 18th 2016 Week 34th Thursday

    Comedy is acting out optimism. 喜剧就是将乐观演绎出来. Being optimistic or pessimistic, that is all about your ...

  8. NYOJ题目113字符串替换

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAr4AAAHvCAIAAAA930vtAAAgAElEQVR4nO3dPVLjysIG4G8T5CyE2A ...

  9. PHP面向对象——异常处理

    Error_reporting(0);  //在网站正式上线的时候不准他报任何错误.  错误级别为不允许报错 Exception 是所有异常的基类. 测试并捕捉一个错误的例子:  class mysq ...

  10. sql server 的cpu使用率过高的分析

    有哪些SQL语句会导致CPU过高? 1.编译和重编译 编译是 Sql Server 为指令生成执行计划的过程.Sql Server 要分析指令要做的事情,分析它所要访问的表格结构,也就是生成执行计划的 ...