js模式与设计模式

优点:

1.封装私有变量---对于上来就初始化且不让修改的,对于只需执行一次的工作

2.变量用于自调用函数不污染全局变量,封装模块提供一个作用域沙箱

用于

初始化分支

var util = {

addListener:function(ele,type,handle){

if (typeof window.addEventListener ===‘function‘) {

ele.addEventListener(type,handle,false);

}else if (typeof document.attachEvent === ‘function‘) {

ele.attachEvent(‘on‘+type,handle);

}else{

ele[‘on‘+type]=handle;

}

}

}

上面这段代码要每次都会检测效率低下

整个生命周期内只需检测一次所以优化

var util = {

addListener:null,

removeListener:null

}

if (typeof window.addEventListener ===‘function‘) {

util.addListener=function(ele,type,fn){

ele.addEventListener(type,fn,false);

}else if (typeof document.attachEvent === ‘function‘) {

util.addListener = function(ele,type,fn){

ele.attachEvent(‘on‘+type,fn);

};

}else{

util.addListener=function(ele,type,fn){

ele[‘on‘+type] = fn;

};

}

};

探测浏览器

函数属性----备忘模式

缓存结果

var myFunc = function(param){

if (!myFunc.cache[param]) {

var result = {};

myFunc.cache[param] = result;

};

return myFunc.cache[param];

};

myFunc.cache = {};

优化---可以传复杂参数

var myFunc = function(){

var cachekey = JSON.stringify(Array.prototype.slice.call(arguments)),result;

if (!myFunc.cache[cachekey]) {

result = {};

var result = {};

myFunc.cache[cachekey] = result;

};

return myFunc.cache[cachekey];

};

myFunc.cache = {};

命名空间

var MYAPP = MYAPP||{};

MYAPP.namespace = function(ns_string){

var parts = ns_string.split("."),

parent = MYAPP,

i;

if (parts[0] ==="MYAPP") {

parts = parts.slice(1);

};

for (var i = 0,len = parts.length; i <len; i++) {

//如果不存在就创建一个属性

if (typeof parent[parts[i]]===‘undefined‘) {

parent[parts[i]] ={};

};

parent=parent[parts[i]];

};

return parent;

}

声明依赖:

优点

1.显式声明依赖向代码用户表明他们需要的脚本已加载进页面

2.在函数的顶部声明很容易发现并解析依赖

3.解析局部变量快于全局变量

var myFunc = function(){
   var event =
YAHOO.util.Event,
       dom = YAHOO.util.Dom;
}

私有变量:---即局部变量

特权方法:---可以访问私有成员的公有方法(对象字面量级私有、原型和私有、揭示模式)

//对象字面量及私有性

var myobj;

(function(){

var
name="xiaoyu";

myobj = {

getName:function(){

return
name;

}

};

}());

原型和私有

function Gadget(){

var name=‘iPod‘;

this.getName =
function(){

return
name;

};

}

Gadget.prototype = (function(){

var browser =
"mobile webkit";

return {

getBrowser:function(){

return
browser;

}

}

}());

var toy = new Gadget();

console.log(toy.getName());//特权“own”方法

console.log(toy.getBrowser());//特权原型方法

揭示模式

var myarray =
(function(){

var astr = "[object
Array]",

toString = Object.prototype.toString;

function isArray(a){

return tiString.call(a)===astr;

}

function
indexOf(haystack,needle){

var
i =0,max = haystack.length;

for(;i<max;i++){

if
(haystack[i] === needle) {

return
i;

};

}

return
-1;

}

myarray = {

isArray:isArray,

indexOf:indexOf,

inArray:indexOf

}

});

//模块模式

// 命名空间

// 即时函数

// 私有和特权成员

// 声明依赖

MYAPP.namespace(‘MYAPP.util.array‘);

MYAPP.util.array = (function(){

// 依赖

var uobj =
MYAPP.util.object,

ulang = MYAPP.prototype.lang,

// 私有属性

array_string = "[object Array]",

ops = Object.prototype.toString;

// 私有方法

// 可选一次性初始化过程

// 公有API

return{

inArray:function(needle,haystack){

for(var
i=0,max=haystack.length;i<max;i+=1){

if
(haystack[i]===needle) {

return
true;

};

}

},

isArray:function(a){

return
ops.call(a) === array_string;

}

}

})

// 创建构造函数的模块

MYAPP.namespace(‘MYAPP.util.Array‘);

MYAPP.util.Array = (function(){

var uobj = MYAPP.util.object,

ulang = MYAPP.prototype.lang,

// 私有属性

Constr;

// ....

Constr = function(o){

this.ele =
this.toArray(o);

};

Constr.prototype ={

constructor:MYAPP.util.Array,

version:"2.0",

toArray:function(obj){

for(var
i=0,a=[].len=obj.length;i<len;i+=1){

a[i]
= obj[i];

}

return
a;

}

return Constr;

}

});

// 沙箱模式

function Sandox(){

var args =
Array.prototype.slice.call(arguments),

callback = args.pop(),

modules = (args[0]&& typeof args[0]
===‘string‘)?args:args[0],i;

// 确保该函数作为构造函数调用

if (!(this instanceof Sandox)) {

return new
Sandox(modules,callback);

}

this.a = 1;

this.b=2;

// 向该核心this添加模块

if (!modules||modules==="*") {

modules = [];

for(i in
Sandox.modules){

if
(Sandox.modules.hasOwnProperty) {

modules.push(i);

};

}

};

// 初始化需要加载的模块

for(i=0;i<modules.length;i+=1){

Sandox.modules[modules[i]](this);

}

callback(this);

}

Sandox.modules = {};

Sandox.modules.dom = function(box){

box.getElement = function(){};

box.getStyle = function(){};

box.foo = "bar";

}

// Sandox.modules.event =
function(){.....}

// Sandox.modules.ajax = function(){}

Sandox(‘ajax‘,‘dom‘,function(box){

// ....

})

链模式

优点

1.节省输入一些字符,是代码简洁

2.可以帮助您考虑翻个函数。穿件更加简短具有特定功能的函数提高代码的可维护性

缺点:

代码难以调试

方法:当代吗没有明显和有意义的返回值时可以返回this

method方法

// method

Function.prototype.method
= function(name,implementation){

if(typeof
Function.prototype.method!=="function"){

Function.prototype.method
= function(name,implementation){

this.prototype[name]
= implementation;

return
this;

}

}

}

var Person = function(name){

this.name =name;

}.method(‘getName‘,function(){
   return
this.name;
}).method(‘setName‘,function(){

return this;

})

单体模式({}就是一个单体)

使用new操作符穿件多个对象时,应尽获得指向完全相同的对象的新指针

1静态属性缓存

function Universe(){

if(typeof Universe.instance ==="object"){

return Universe.instance;

}

this.start_time = 0;

this.bang = "Big";

Universe.instance = this;

// return this;

}

var uni = new Universe();

var uni2 = new Universe();

uni===uni2;

//缺点该实例属性是公开的

闭包中的实例   ---缺点是带来了额外的开销

function Universe(){

this.start_time = 0;

this.bang = "Big";

var instance = this;

Universe = function (){

return instance;

}

// return this;

}

Universe.prototype.nothing  =true;

var uni = new Universe();

Universe.prototype.everything=true;

var uni2 = new Universe();

Universe.prototype.something  =true;

uni===uni2;

uni===uni2;

true

uni.nothing

true

uni2.nothing

true

uni.everything

undefined

uni.something

undefined

注释:第一次调用想往常一样返回this以后Universe被重写为

function (){

return instance;

}一直引用着instance

缺点当第一次调用后为原型添加属性方法不会被添加到实例上

改进

function Universe(){

// 缓存实例

var instance;

// 保留原型属性 此时的Universe是重写或的构造函数this是重写之前的

Universe = function Universe(){

return instance;

}

// 保留原型属性

Universe.prototype = this;

instance = new Universe();

instance.constructor = Universe;

instance.start_time = 0;

instance.bang = "big";

return instance;

}

方法二

即时函数

var Universe;

(function(){

var instance;

Universe = function Universe(){

if(instance){

return instance;

}

instance = this;

this.start_time=0;

this.bang = "big";

};

}());

工厂模式

找到要穿件的构造函数即可return相应对象

function CarMaker(){}

CarMaker.prototype.dirve = function(){

return "Vroom,I have "+this.doors+" doors";

};

CarMaker.factory = function(type){

var constr = type,newcar;

if(typeof CarMaker[constr] !== "function"){

throw{

name:"Error",

message:constr + " doesn‘t exist"

};

}

if(typeof CarMaker[constr].prototype.dirve !== "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;

}

迭代器模式

var agg = (function(){

var index =0,data=[1,2,3,4,5],length=data.length;

return{

next:function(){

var element;

if(!this.hasNext()){

return null;

}

element = data[index];

index+=2;

return element;

},

hasNext:function(){

return index < length;

},

rewind:function(){

index = 0;

},

current:function(){

return data[index];

}

}

}());

// 装饰者模式

function Sale(price){

this.price = price ||100;

}

Sale.prototype.getPrice = function(){

return this.price;

}

Sale.decorators ={};

Sale.decorators.fedtax = {

getPrice:function(){

var price = this.uber.getPrice();

price += price*5/100;

return price;

}

};

Sale.decorators.quebec = {

getPrice:function(){

var price = this.uber.getPrice();

price += price*7.5/100;

return price;

}

};

Sale.decorators.money = {

getPrice:function(){

return "$"+this.uber.getPrice().toFixed(2);

}

};

Sale.decorators.cdn = {

getPrice:function(){

return "CDN$"+this.uber.getPrice().toFixed(2);

}

};

Sale.prototype.decorators = function(decorator){

var F = function(){},

overrides = this.constructor.decorators[decorator]; //this.constructor---Sale.prototype.constructor指向的是Sale

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;

}

// 使用列表实现

function Sale(price){

this.price = price ||100;

this.decorators_list =[];

}

Sale.prototype.getPrice = function(){

return this.price;

}

Sale.decorators ={};

Sale.decorators.fedtax = {

getPrice:function(price){

price += price*5/100;

return price;

}

};

Sale.decorators.quebec = {

getPrice:function(price){

price += price*7.5/100;

return price;

}

};

Sale.decorators.money = {

getPrice:function(price){

return "$"+price.toFixed(2);

}

};

Sale.decorators.cdn = {

getPrice:function(price){

return "CDN$"+price.toFixed(2);

}

};

Sale.prototype.decorators = function(decorator){

this.decorators_list.push(decorator);

};

Sale.prototype.getPrice = function(){

var price = this.price,  //

this

Sale {price: 200, decorators_list: Array[2], decorators: function, getPrice: function}this指向的是构造函数

i,max = this.decorators_list.length,

name;

for(i = 0;i<max;i+=1){

name = this.decorators_list[i];

price = Sale.decorators[name].getPrice(price);

}

return price;

}

策略这模式

支持运行时选择算法代码客户端可以使用同一个接口工作单她根据客户正在试图执行任务的上下文荀泽处理特定人去的算法

var data = {

first_name:"super",

last_name:"Man",

age:"unknown",

username:"LS"

}

var validator = {

types:{},

messages:[],

config:{},

validate:function(data){

var i,msg,type,checker,result_ok;

this.messages =[];

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 handle to validate type"+type

};

}

result_ok = checker.validate(data[i]);

if(!result_ok){

msg = "Invalid value for *"+i+"*,"+checker.instructions;

this.messages.push(msg);

}

}

}

return this.hasErrors();

},

hasErrors:function(){

return this.messages.length !== 0;

}

}

validator.config = {

first_name:‘isNonEmpty‘,

age:‘isNumber‘,

username:‘isAlphaNum‘

}

validator.types.isNonEmpty ={

validate:function(value){

return value!=="";

},

instructions:"the value cannot be empty"

}

validator.types.isNumber ={

validate:function(value){

return !isNaN(value);

},

instructions:"the value can only be a valid number,"

}

validator.types.isAlphaNum ={

validate:function(value){

return !/[^a-z0-9]/i.test(value);

},

instructions:"the value can only be contain characters and numbers,no special aymbols"

}

validator.validate(data);

if (validator.hasErrors()) {

console.log(validator.messages.join("\n"));

};

Invalid value for *age*,the value can only be a valid number,

外观者模式

为对象提供一个可供选择的接口

(有时两个或多个方法可能普遍的被一起调用,这时川建一个方法一包装重复的方法调用非常有意义)

浏览器事件--stopPropagation()   preventDefault()

var myevent={

stop:function(e){

if(typeof e.preventDefault ==="function"){

e.preventDefault();

}

if(typeof e.stopPropagation==="function"){

e.stopPropagation();

}

if(typeof e.returnValue ==="boolean"){

e.returnValue = false;

}

if(typeof e.cancelBubble ==="boolean"){

e.cancelBubble = false;

}

}

}

var EventUtil = {

addHandler: function(element, type, handler){

if (element.addEventListener){

element.addEventListener(type, handler, false);

} else if (element.attachEvent){

element.attachEvent("on" + type, handler);

} else {

element["on" + type] = handler;

}

},

getButton: function(event){

if (document.implementation.hasFeature("MouseEvents", "2.0")){

return event.button;

} else {

switch(event.button){

case 0:

case 1:

case 3:

case 5:

case 7:

return 0;

case 2:

case 6:

return 2;

case 4: return 1;

}

}

},

getCharCode: function(event){

if (typeof event.charCode == "number"){

return event.charCode;

} else {

return event.keyCode;

}

},

getClipboardText: function(event){

var clipboardData =  (event.clipboardData || window.clipboardData);

return clipboardData.getData("text");

},

getEvent: function(event){

return event ? event : window.event;

},

getRelatedTarget: function(event){

if (event.relatedTarget){

return event.relatedTarget;

} else if (event.toElement){

return event.toElement;

} else if (event.fromElement){

return event.fromElement;

} else {

return null;

}

},

getTarget: function(event){

return event.target || event.srcElement;

},

getWheelDelta: function(event){

if (event.wheelDelta){

return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);

} else {

return -event.detail * 40;

}

},

preventDefault: function(event){

if (event.preventDefault){

event.preventDefault();

} else {

event.returnValue = false;

}

},

removeHandler: function(element, type, handler){

if (element.removeEventListener){

element.removeEventListener(type, handler, false);

} else if (element.detachEvent){

element.detachEvent("on" + type, handler);

} else {

element["on" + type] = null;

}

},

setClipboardText: function(event, value){

if (event.clipboardData){

event.clipboardData.setData("text/plain", value);

} else if (window.clipboardData){

window.clipboardData.setData("text", value);

}

},

stopPropagation: function(event){

if (event.stopPropagation){

event.stopPropagation();

} else {

event.cancelBubble = true;

}

}

};

代理模式----以一个对象充当另一个对象的接口

与外观模式的区别

外观模式是拥有合并了多个方法调用的遍历方法代理则是介于对象客户端与对象本身之间并且对该对象的访问进行保护

优点:使用代理可以合并和减少到服务器的往返次数

典型的是延迟初始化

事件代理事件处理程序

进一步优化----缓存代理(缓存请求的结果cache)

中介者:在多对象之间回旋

观察者模式-------------自定义事件订阅/发布模式

所有浏览器事件是该模式(鼠标悬停,按键等事件)例子

这种模式不是一个对象调用另一个对象的方法而是一个对象的特定活动并在状态改变后获得通知

订阅者为观察者

时间: 2024-10-28 20:37:23

js模式与设计模式的相关文章

JS常用的设计模式(8)——访问者模式

GOF官方定义: 访问者模式是表示一个作用于某个对象结构中的各元素的操作.它使可以在不改变各元素的类的前提下定义作用于这些元素的新操作.我们在使用一些操作对不同的 对象进行处理时,往往会根据不同的对象选择不同的处理方法和过程.在实际的代码过程中,我们可以发现,如果让所有的操作分散到各个对象中,整个系统会变得 难以维护和修改.且增加新的操作通常都要重新编译所有的类.因此,为了解决这个问题,我们可以将每一个类中的相关操作提取出来,包装成一个独立的对象,这 个对象我们就称为访问者(Visitor).利

JS常用的设计模式(17)—— 状态模式

状态模式主要可以用于这种场景 1 一个对象的行为取决于它的状态 2 一个操作中含有庞大的条件分支语句 回想下街头霸王的游戏. 隆有走动,攻击,防御,跌倒,跳跃等等多种状态,而这些状态之间既有联系又互相约束.比如跳跃的时候是不能攻击和防御的.跌倒的时候既不能攻击又不能防御,而走动的时候既可以攻击也可以跳跃. 要完成这样一系列逻辑, 常理下if else是少不了的. 而且数量无法估计, 特别是增加一种新状态的时候, 可能要从代码的第10行一直改到900行. if ( state === 'jump'

JS常用的设计模式(15)—— 职责链模式

职责链模式是一个对象A向另一个对象B发起请求,如果B不处理,可以把请求转给C,如果C不处理,又可以把请求转给D.一直到有一个对象愿意处理这个请求为止. 打个比方,客户让老板写个php程序.老板肯定不写,然后老板交给了部门经理.部门经理不愿意写,又交给项目经理.项目经理不会写,又交给程序员.最后由码农来完成. 在这个假设里, 有几条职责链模式的特点. 1 老板只跟部门经理打交道,部门经理只联系项目经理,项目经理只找码农的麻烦. 2 如果码农也不写,这个项目将会流产. 3 客户并不清楚这个程序最后是

JS常用的设计模式(14)—— 备忘录模式

备忘录模式在js中经常用于数据缓存. 比如一个分页控件, 从服务器获得某一页的数据后可以存入缓存.以后再翻回这一页的时候,可以直接使用缓存里的数据而无需再次请求服务器. 实现比较简单,伪代码: var Page = function(){ var page = 1, cache = {}, data; return function( page ){ if ( cache[ page ] ){ data = cache[ page ]; render( data ); }else{ Ajax.s

JS常用的设计模式(11)—— 中介者模式

中介者对象可以让各个对象之间不需要显示的相互引用,从而使其耦合松散,而且可以独立的改变它们之间的交互. 打个比方,军火买卖双方为了安全起见,找了一个信任的中介来进行交易.买家A把钱交给中介B,然后从中介手中得到军火,卖家C把军火卖给中介,然后 从中介手中拿回钱.一场交易完毕,A甚至不知道C是一只猴子还是一只猛犸.因为中介的存在,A也未必一定要买C的军火,也可能是D,E,F. 银行在存款人和贷款人之间也能看成一个中介.存款人A并不关心他的钱最后被谁借走.贷款人B也不关心他借来的钱来自谁的存款.因为

JS常用的设计模式(12)—— 迭代器模式

迭代器模式提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该方法中的内部表示. js中我们经常会封装一个each函数用来实现迭代器. array的迭代器: forEach = function( ary, fn ){ for ( var i = 0, l = ary.length; i < l; i++ ){ var c = ary[ i ]; if ( fn.call( c, i , c ) === false ){ return false; } }} forEach( [ 1,

JS常用的设计模式(2)——简单工厂模式

简单工厂模式是由一个方法来决定到底要创建哪个类的实例, 而这些实例经常都拥有相同的接口. 这种模式主要用在所实例化的类型在编译期并不能确定, 而是在执行期决定的情况. 说的通俗点,就像公司茶水间的饮料机,要咖啡还是牛奶取决于你按哪个按钮. 简单工厂模式在创建ajax对象的时候也非常有用. 这个库里提供了几种ajax请求的方式,包括xhr对象的get, post, 也包括跨域用的jsonp和iframe. 为了方便使用, 这几种方式都抽象到了同一个接口里面. 1 var request1 = Re

JS常用的设计模式(9)——策略模式

策略模式的意义是定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.一个小例子就能让我们一目了然. 回忆下jquery里的animate方法. $( div ).animate( {"left: 200px"}, 1000, 'linear' ); //匀速运动 $( div ).animate( {"left: 200px"}, 1000, 'cubic' ); //三次方的缓 这2句代码都是让div在1000ms内往右移动200个像素. linear(

JS常用的设计模式(7)—— 外观模式

外观模式(门面模式),是一种相对简单而又无处不在的模式.外观模式提供一个高层接口,这个接口使得客户端或子系统更加方便调用.用一段再简单不过的代码来表示 var getName = function(){ return ''svenzeng" } var getSex = function(){ return 'man' } 如果你需要分别调用getName和getSex函数. 那可以用一个更高层的接口getUserInfo来调用. var getUserInfo = function(){ va