JS设计模式系列2

  • 结构型设计模式
  • 一、外观模式
  • 1.1. 引言:添加一个点击事件
  • 1.2 兼容方式
  • 二、适配器模式
  • 2.1 适配异类框架
  • 2.2参数适配器
  • 装饰者模式【神了】


结构型设计模式

结构型设计模式关注如何将类或对象组合成更大更复杂的结结构,以简化设计

一、外观模式

外观模式: 为一组复杂的子系统接口提供一个更高级的统一接口,通过这个接口使得对子系统的结果更容易访问
emm,这里我第一个想到的就是前端对axios的封装,以及把某个角色或某个功能的api接口单独写在一个js文件里,调用时直接引用文件即可。

1.1. 引言:添加一个点击事件

代码示例

document.onclick = function (e) {
	e.preventDefault()
	if (e.target !== document.getElementById('myinput')){
		hidePageAlert()
	}
}

function hidePageAlert(){}

问题1: onclick是DOM0级元素,当其他人再为document绑定方法时,会覆盖原先的方法。
问题2: 针对,问题1,应该采用DOM2级事件处理程序提供的方法addEventListener实现。但这里需要考虑浏览器兼容的问题
问题3: e.preventDefault()和e.target()也需要考虑兼容的问题

1.2 兼容方式

事件处理

// 外观模式实现事件处理
function addEvent(dom,type,fn) {
	// 对于支持DOM2级事件处理程序addEventListener方法的浏览器
	if (dom.addEventListener){
		dom.addEventListener(type,fn,false)
	}
	// 对于支持attachEvents的浏览器
	else if (dom.attachEvents){
		dom.attachEvents('on' + type,fn)
	}
	// 对于不支持addEvent... 和 attach...,但支持on+'事件名'
	else {
		dom['on'+type]=fn
	}
}

e.targete.preventDefault

//获取事件对象
var getEvent = function (event){
	// IE下是window.event
	return event || window.event
}

// 获取元素
var getTarget = function (event) {
	var event = getEvent(event)
	return event.target || event.srcElement
}

var preventDefault = function (event) {
	var event = getEvent(event)
	if (event.preventDefault()) {
		event.preventDefault()
	}	else{
		event.returnValue = false
	}
}

二、适配器模式

适配器模式: 将一个类(对象)的接口转换成另一个接口,使类之间接口的不兼容问题通过适配器得以解决

2.1 适配异类框架

A框架代码

var A = A || {}
a.g = function (id) {
	return document.getElementById(id)
}


A.on = function (id,type,fn){
	var dom = typeof id === 'string' ? this.g(id) : id
	if (dom.addEventListener) {
		dom.addEventListener(type, fn, false)
	}
	else if (dom.attachEvents) {
		dom.attachEvents('on' + type, fn)
	}
	else {
		dom['on' + type] = fn
	}
}

适配jquery

A.g = function (id) {
	return $(id).get(0)
}

A.on = function (id, type, fn) {
	var dom = typeof id === 'string' ? $('#' + id) : $id
	dom.on(type,fn)
}

2.2参数适配器

用途1: 若方法需要传递多个参数,可以以一个参数对象方式传入
用途2: 调用时不知传递的参数是否完整,此时可以用适配器来适配传入的对象

// 适配传入的对象
function doSomeThing(obj) {
	var _adapter = {
		name:'wjyGrit',
		title:'设计模式',
		age:19,
		color:'blue',
		size:100,
		prize:50
	}
	for (var i in _adapter){
		_adapter[i] = obj[i] || _adapter[i]
	}
	// do things
}

装饰者模式【神了】

装饰者模式 在不改变原对象的基础上,通过对其进行包装扩展,使原有对象可以满足用于的更复杂需求
需求:给用户信息输入框增加一些需求,需要改多个,而且还是不改变原有功能,如果一个一个改又不太好

代码展示
这样,无论输入框是否绑定过输入事件,都可以轻松完成需求,后期再更改也方便

var decorator = function (input, fn) {
	var input = document.getElementById(input) //获取事件源
	// 若事件源已经绑定事件[还可以这样!!!]
	if (typeof input.onclick === 'function') {
		// 缓存事件源原有的回调函数
		var oldClickFn = input.onclick
		// 为事件源定义新的事件
		input.onclick = function () {
			// 事件源原有回调函数
			oldClickFn()
			fn(0)
		}
	} else {
		// 事件源未绑定事件,直接为事件源添加新增回调函数
		input.onclick = fn
	}
	//others
}


decorator('tel_input',function () {
	document.getElementById('tel_demo_text').style.display = 'none'
})