接下来就是第三篇啦!!!更加的复杂了我感觉。。休息一下开始。
第三篇 结构型设计模式
//外观模式实现 function addEvent( dom , type , fn ) { // 对于支持DOM2级事件处理程序addEvenListener方法的浏览器 if ( dom.addEventListener) { dom.addEventListener( type , fn , false ); } else if ( dom.attachEvent) { // 对于支持attachEvent方法的浏览器 dom.attachEvent('on' + type , fn); } else { // 对于这2种方法都不支持的浏览器 dom [ 'on' + type ] = fn; } } var myInput = document.getElementById('myinput'); addEvent( myInput , 'click' , function () { console.log ( '绑定我的第一个事件' ); } ); addEvent( myInput , 'click' , function () { console.log ( '绑定我的第二个事件' ); } );
这样子这个函数就可以复用了,而且不会与后来其他的事件起冲突。
接下来是参数适配器:
/* * obj.name : name * obj.age : age * obj.title : title * obj.color : color * obj.size : size * obj.price : price */ function doSomething( obj ) { var _adapter = { name : '罗浩浩', age : 18, title : '设计模式', color : 'red', size : 100, price : 30 }; for ( var i in _adapter) { _adapter[i] = obj[i] || _adapter[i]; } }
目的呢是调用的时候不知道参数传递的是否完整,所以用适配器来传入参数对象。
下面一个是数据适配,一般的数组我们会发现每个成员代表的意义不明确,我们就可以用下面这样的形式:
var obj = { name : '' , type : '' , title : '' , time : '' }; function arrToObjectAdapter( arr ) { return { name : arr[0], type : arr[1], title : arr[2], data : arr[3] } } var arr = ['js','book','前端编程语言','8月1日']; var adapterData = arrToObjectAdapter( arr ); console.log ( adapterData ); // name: "js" type: "book" title: "前端编程语言" time: "8月1日"
装饰者模式:
var decorator = function ( input , fn ) { // 获取事件源 var input = document.getElementById(input); // 若事件源是已经绑定的事件 if ( typeof input.onclick === 'function' ) { // 缓存事件原有的回调函数 var oldClickFn = input.onclick; // 为事件源添加新的事件 input.onclick = function () { // 事件源原有回调函数 oldClickFn(); // 执行事件源新增回调函数 fn(); } } else { // 事件源未绑定事件,直接为事件源添加新增回调函数 input.onclick = fn; } }; // 电话输入框功能装饰 decorator( 'tel_input' , function () { document.getElementById( 'tel_demo_text' ).style.display = 'none' ; } )
着实是。。有点摸不着头脑,这里我要去问问啦~
下一个!我已经要死了。。桥接模式:
var spans = document.getElementsByTagName('span'); spans[0].onmouseover = function () { this.style.color = 'pink'; this.style.bakcground = '#ccc'; }; spans[0].onmouseout = function () { this.style.color = ''; this.style.bakcground = ''; }; spans[1].onmouseover = function () { this.getElementsByTagName('strong')[0].style.color = 'red'; this.style.bakcground = '#pink'; }; spans[1].onmouseout = function () { this.getElementsByTagName('strong')[0].style.color = ''; this.style.bakcground = ''; };
html和css我局不写了。。偷个懒,主要是js。。。
这么写,好恶心啊,看着很不爽啊!那我么就用抽象化的思维,提取一下共同点。说白了,就是要有一个标签,然后要让他变色,那就再给他一个方法。那就是。。function(dom,color,bg)
function changeColor ( dom , color , bg ) { dom.style.color = color; dom.style.background = bg; } var spans = document.getElementsByTagName('span'); spans[0].onmouseover = function () { changeColor( this , 'pink' , '#ccc' ) };
这一下就舒服多了嘛!!!
接下来是多元化对象!!!!疯了!!记不住那么多啊!
// 运动单元 function Speed( x , y ) { this.x = x; this.y = y; } Speed.prototype.run = function () { console.log ( '动起来' ); }; // 着色单元 function Color( cl ) { this.color = cl; } Color.prototype.draw = function () { console.log ( '绘制色彩' ); }; //说话单元 function Speak( wd ) { this.word = wd; } Speak.prototype.say = function () { console.log ( '书写字体' ); }; // 创建一个球类,并且它可以运动,可以着色 function Ball( x ,y, c ) { this.speed = new Speed ( x , y ); this.color = new Color ( c ); } Ball.prototype.init = function () { this.speed.run(); this.color.draw(); }; // 创建一个人,它可以说话,可以运动 function Human( x , y , f ) { this.speed = new Speed ( x , y ); this.font = new Speak ( f ); } Human.prototype.init = function () { this.speed.run(); this.font.say(); }; var person = new Human ( 10 , 12 , 16 ); // 动起来 person.init(); // 书写字体
这就是多元化对象。。其中当我们想做什么的时候,就实例化一个人物对象,这样他就有运动和说话的动作了。
桥接模式可以实现将元素的事件与业务逻辑之间解耦。也可以更加灵活的创建一个对象。他最大的特点就是将实现层(如元素绑定的事件)与抽象层(如修饰页面的UI逻辑)相分离,使得两边都可以有独立的变化。避免需求的改变而对对象内部的修改,体现了面向对象对括展的开放和对修改的关闭的原则。
受不鸟啦!!!明天再接着来!!