js设计模式1.工厂模式 function Person(name) { this.name = name;}function Car(model) { this.model = model}// 根据选择的类类型来创建实例对象(只需把类都挂载此工厂函数的原型上,再调用)function creat
function Person(name) {
this.name = name;
}
function Car(model) {
this.model = model
}
// 根据选择的类类型来创建实例对象(只需把类都挂载此工厂函数的原型上,再调用)
function createEntity(type,params){
// 如果外部使用了new关键字
if(this instanceof createEntity){
return new this[type](params)
}else{// 如果没有使用new关键字
return new createEntity(type,params)
}
}
createEntity.prototype = {
Person,
Car
}
console.log(new createEntity('Car','OOOO'));
console.log(new createEntity('Person','TOM'));
2.建造者模式
function Person(name) {
this.name = name;
}
function CreateCar(model) {
this.model = model
}
function CreateHouse(area) {
this.area = area
}
// 构建者模式方便于建立复合对象模型
function personInfo(name,model,area) {
let _person = new Person(name)
_person.car = new CreateCar(model)
_person.area = new CreateHouse(area)
return _person
}
console.log(personInfo('BON','OOOO',360));
3.单例模式
// 单例模式,就是都使用创建唯一的一个对象,利用函数闭包实现
let createSingle(function(){
let _unique = null;
function single(){
return {a:1}
}
return function() {
if(_unique === null){
_unique = single();
}
return _unique
}
})()
console.log(createSingle() === createSingle()) // true
4.装饰器模式
// 希望在不改变原对象的基础上,通过对其拓展功能和属性来实现更复杂的逻辑
function Person(name) {
this.name = name;
this.wealth = 2
}
function createCar(item) {
item.car = true
item.wealth += 1
}
function createHouse(item) {
item.house = true
item.wealth += 1
}
let aa = new Person('name')
createCar(aa)
createHouse(aa)
console.log(aa);
5.组合模式
/**
* 组合模式就是对经常使用的相同组件的一个封装,利用js创建出来
* 避免了编写重复代码,相当于用作一个插件,快速构建DOM并渲染
*
*/
function inheritPrototype (superClass,subClass) {
const F = function() {};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
}
function Container(){
this.children = []
this.element = null
}
Container.prototype = {
init: function () {
throw new Error("请重写init方法!")
},
add: function (child) {
this.children.push(this.element)
this.element.appendChild(child.element)
return this
}
}
function CreateForm(id,method,action,parent) {
Container.call(this)
this.id = id || ''
this.method = method || 'GET'
this.action = action || ''
this.parent = parent
this.init()
}
inheritPrototype(Container,CreateForm)
CreateForm.prototype.init = function () {
this.element = document.createElement('form')
this.element.id = this.id
this.element.method = this.method
this.element.action = this.action
}
CreateForm.prototype.show = function () {
this.parent.appendChild(this.element)
}
function CreateLine(className) {
Container.call(this)
this.className = className === undefined ? 'form-line' : 'form-line ' + className
this.init()
}
inheritPrototype(Container,CreateLine)
CreateLine.prototype.init = function () {
this.element = document.createElement('div')
this.element.className = this.className
}
function CreateLabel(text,forName){
this.text = text || ''
this.forName = forName
this.init()
}
CreateLabel.prototype.init = function () {
this.element = document.createElement('label')
this.element.setAttribute('for',this.forName)
this.element.innerHTML = this.text
}
function CreateInput(type,id,name,defaultValue) {
this.type = type || ''
this.id = id || ''
this.name = name || ''
this.defaultValue = defaultValue || ''
this.init()
}
CreateInput.prototype.init = function () {
this.element = document.createElement('input')
this.element.type = this.type
this.element.id = this.id
this.element.name = this.name
this.element.value = this.defaultValue
}
var form = new CreateForm('owner-form','get','./aa.html',document.body)
var userLabel = new CreateLabel('账户','user')
var userInput = new CreateInput('text','user','user')
var userLine = new CreateLine('user').add(userLabel).add(userInput)
var pwdLabel = new CreateLabel('密码','pwd')
var pwdInput = new CreateInput('password','pwd','pwd')
var pwdLine = new CreateLine('pwd').add(pwdLabel).add(pwdInput)
var submitLine = new CreateLine('submit').add(new CreateInput('submit','','','登录'))
form.add(userLine).add(pwdLine).add(submitLine).show()
6.观察者模式
// 订阅者订阅消息==>消息中心,注册订阅者以及接受消息方法函数==>消息中心发布消息,执行订阅者的消息方法函数
const msgCenter = (function() {
let _msg = {}
return {
subscribe(type,fn) {
if(_msg[type]){
_msg[type].push(fn)
}else{
_msg[type] = [fn]
}
},
release(type,args = {}) {
if(!_msg[type]) return;
let event = {type,args};
for(let i = 0; i < _msg[type].length; i++){
_msg[type][i](event);
}
},
cancel(type,fn) {
if(!_msg[type]) return;
for(let i = 0; i < _msg[type].length; i++){
if(_msg[type][i] === fn) _msg[type].splice(i,1)
}
}
}
})()
function Person(name){
this.name = name
this.subscribed = {}
}
Person.prototype.subscribe = function (type,fn) {
if(this.subscribed[type]) return;
this.subscribed[type] = fn;
msgCenter.subscribe(type,fn)
}
Person.prototype.cancel = function (type) {
msgCenter.cancel(type,this.subscribed[type])
if(this.subscribed[type]) delete this.subscribed[type]
}
let p1 = new Person('p1')
p1.subscribe("info_1",(e)=>{
console.log(`${p1.name}:你订阅了 ${e.type},收到的内容是:${e.args.msg}`);
})
p1.subscribe("info_2",(e)=>{
console.log(`${p1.name}:你订阅了 ${e.type},收到的内容是:${e.args.msg}`);
})
let p2 = new Person('p2')
p2.subscribe("info_2",(e)=>{
console.log(`${p2.name}:你订阅了 ${e.type},收到的内容是:${e.args.msg}`);
})
msgCenter.release('info_1',{msg:'这是msgCenter发布的第一则消息'})
msgCenter.release('info_2',{msg:'这是msgCenter发布的第二则消息'})
7.策略模式
// 通过函数闭包,自定义策略来匹配一些模式是否符合规则
function formStrategy(){
let strategy = {
isEmpty(value) {
return value.length ? '' : 'input some information in here,please'
},
isNumber(value) {
let reg = /^[0-9]+(\.[0-9]+)?$/;
return reg.test(value) ? '' : 'required a type of number at here'
},
isPhone(value) {
let reg = /^\d{3}-\d{8}$|^\d{4}-\d{7}$/;
return reg.test(value) ? '' : 'required a tele-number at here'
}
}
return {
validate(type,value){
value = value.replace(/^\s+|\s+$/,'')
return strategy[type] ? strategy[type](value) : "there doesn't exit a function,add it manually!"
},
addStrategy(type,fn){
if(strategy[type]){
return 'it has this method already'
}else {
strategy[type] = fn;
}
}
}
}
8.链模式模式
类如jquery的链式调用编程
9.委托模式事件代理(委托)
10.数据访问对象模式/**
* @params nameSpace|key:expire|value
*
*/
let DataVisitor = function(nameSpace,splitSign) {
this.nameSpace = nameSpace
this.splitSign = splitSign || '|'
}
DataVisitor.prototype = {
status : {
SUCCESS: 0,
FAILURE: 1,
OVERFLOW: 2,
TIMEOUT: 3
},
createKey(key){
return this.nameSpace + this.splitSign + key
},
createVal(expire,value){
typeof expire === 'number' ? expire += new Date().getTime() : expire = -1
return expire + this.splitSign + value
},
set(key,value,cb,expire){
let status = this.status.SUCCESS
key = this.createKey(key);
value = this.createVal(expire,value)
try{
window.localStorage.setItem(key,value)
}catch(e){
status = this.status.OVERFLOW
}
cb && cb.call(this,status,key,value)
return this
},
get(key,cb) {
let status = this.status.SUCCESS
key = this.nameSpace + this.splitSign + key
let value = window.localStorage.getItem(key)
if(value){
let time = value.slice(0,value.indexOf(this.splitSign))
if(time > new Date().getTime() || time == -1){
value = value.slice(value.indexOf(this.splitSign) + this.splitSign.length)
}else{
status = this.status.TIMEOUT
value = null
window.localStorage.removeItem(key)
}
}else{
status = this.status.FAILURE
}
cb && cb.call(this,status,key,value)
return this
},
remove(key) {
let status = this.status.FAILURE
key = this.nameSpace + this.splitSign + key
let value = this.localStorage.getItem(key)
if(value) {
value.slice(value.indexOf(this.splitSign) + this.splitSign.length)
status = this.status.SUCCESS
window.localStorage.removeItem(key)
}
cb && cb.call(this,status,key,value)
return this
}
}
function cb() {
console.log(...arguments);
}
var test = new DataVisitor('test')
test.set('aa',123,cb,1000)
test.get('aa',cb)
setTimeout(() => {
test.get('aa',cb)
}, 2000);
10.MVC模式
var MVC = {}
MVC.model = (function () {
data = {
sidebar: [{
title: 'sidebar1',
href: './a.html'
},
{
title: 'sidebar2',
href: './b.html'
},
{
title: 'sidebar3',
href: './c.html'
}]
}
return {
getData(key){
return data[key]
},
setData(key,value){
data[key] = value
}
}
}())
MVC.view = (function () {
let m = MVC.model
let view = {
createDom() {
let data = m.getData('sidebar');
let html = '';
html += '<div id="#sidebar">'
for(let i = 0; i < data.length; i++) {
html += '<div class="side-bar"><a href="'+ data[i].href + '">' + data[i].title + '</a></div>'
}
html += '</div>';
document.body.innerHTML = html;
}
}
return function(v){
view[v]()
}
}())
MVC.ctrl = (() => {
let m = MVC.model;
let v = MVC.view;
return {
initView(){
v('createDom')
},
updateView(){
m.setData('sidebar',[{title: 'newsidebar',href: './n.html'}])
v('createDom')
}
}
})()
window.onload = function () {
MVC.ctrl.initView()
setTimeout(() => {
MVC.ctrl.updateView()
}, 2000);
}
11.MVVM模式
vue数据双向绑定原理
12.等待者模式类如promise(期约),状态机改变才会执行对应状态函数