js-设计模式

js设计模式

1.工厂模式

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(期约),状态机改变才会执行对应状态函数

posted @ 2022-05-03 21:54  star*时光£裔℡  阅读(39)  评论(0编辑  收藏  举报