几种js设计模式

1. 工厂模式

作用:实现对象的批量创建

/* 构造函数 */
function Person(name) {
  this.name = name;
}
function Car(model) {
  this.model = model;
}
/* 创建 */
function create(type, val) {
  return (this instanceof create) ?
    this[type](val) : new create(type, val);
}
create.prototype = {
  person: Person,
  car: Car
}
console.log(create('person', 'zhangsan'))
console.log(new create('car', 'bwm'))

2. 原型模式

作用:创建一个共享原型,通过拷贝这个原型来创建新的类

// 也可以是其他类的原型
let prototype = {
  say() {
    console.log(this.name);
  }
}
function Person() {
  function F() { };
  F.prototype = prototype;
  let f = new F();
  f.name = "zhansan";
  return f;
}
new Person().say();// zhansan

3. 建造者模式

作用:将创建对象的细节分为创建子对象的过程,使结构更加清晰

/* 实现 */
function Person(name) {
  this.name = name;
}

function CreateName(name) {
  this.wholeName = name;
  [this.firstName, this.lastName] = name.split(' ');
}

function CreateWork(workName) {
  switch (workName) {
    case 'engineer':
      this.workName = "工程师";
      this.desc = "热爱编程";
      break;
    case 'teacher':
      this.workName = "老师";
      this.desc = "热爱分享";
      break;
    default:
      this.workName = workName;
      this.desc = "无";
  }
}
CreateWork.prototype.changeWork = function (workName, desc) {
  workName && (this.workName = workName);
  desc && (this.desc = desc);
}
/* 创建类 */
function Candidate(params) {
  let _candidate = new Person();
  _candidate.name = new CreateName(params.name);
  _candidate.work = new CreateWork(params.work);
  return _candidate;
}

/* 举例 */
let arr = [
  { name: "zhang san", work: "engineer" },
  { name: "li si", work: "teacher" }
];
let candidates = [];
arr.forEach(v => {
  candidates.push(new Candidate(v));
})
console.log(candidates[0]);
candidates[0].work.changeWork('学生', '热爱学习');
console.log(candidates[0]);

4. 单例模式

作用:实现无论创建多少个对象都返回同一个

const createSingle = (function () {
  let _unique = null;// 私有变量
  return function () {
    if (_unique === null) {
      _unique = { a: 1 };
    }
    return _unique;
  }
})();

let single1 = createSingle();
let single2 = createSingle();
console.log(single1 === single2);// true

5. 装饰器模式

作用:在不改变原有对象的基础上(也就是不修改原型),拓展功能和属性实现复杂逻辑

/**
 * 4s店在卖一种车,价格为10万元,如果用户需要在此基础上加装一些配置则需要加钱。
 * 比如加热座椅配置需要2万元,电动后视镜需要0.8万元等等。
 */

function Car(price) {
  this.price = price;
}
// 通过函数实现改变(装饰器)
function addHeatSeat(car) {
  car.hasHeatSeat = true;
  car.price += 2;
}
function addAutoMirror(car) {
  car.hasAutoMirror = true;
  car.price += 0.8;
}
let car = new Car(10);
console.log(car);
// Car { price: 10 }
addHeatSeat(car);
addAutoMirror(car);
console.log(car);
// Car { price: 12.8, hasHeatSeat: true, hasAutoMirror: true }

6. 组合模式

作用:将每个组成成分当成一个对象,最终拼成一个整体

  • 组合模式实现一个form表单
    组合模式实现一个form表单
/* 继承原型 */
function inheritClass(Son, Parent) {
  Son.prototype = Object.create(Parent.prototype);
  Son.prototype.constructor = Son;
}
/* 父类 */
function Container() {
  this.element = "";
}
Container.prototype = {
  init() {
    throw new Error("请重写子类init方法");
  },
  add(child) {
    this.element.appendChild(child.element);
    return this;
  }
}
/* 表单 */
function Form(options) {
  // 继承
  Container.call(this);
  // 参数
  this.action = options.action || "/test.html";
  this.method = options.method || "GET";
  this.class = options.class || "";
  this.id = options.id || "";
  this.parentNode = options.parentNode;
  this.init();
}
inheritClass(Form, Container);
Form.prototype.init = function () {
  this.element = document.createElement('form');
  this.element.setAttribute("action", this.action);
  this.element.method = this.method;
  this.element.class = this.class;
  this.element.id = this.id;
}
Form.prototype.show = function () {
  this.parentNode.appendChild(this.element);// 放入父元素
}
/* 标签 */
function Label(options) {
  Container.call(this);
  this.for = options.for || "";
  this.class = options.class || "form-line";
  this.innerText = options.innerText || "";
  this.init();
}
inheritClass(Label, Container);
Label.prototype.init = function () {
  this.element = document.createElement("label");
  this.element.class = this.class;
  this.element.setAtrribute("for",this.for);
  this.element.innerText = this.innerText;
}
/* 输入 */
function Input(options) {
  Container.call(this);
  this.type = options.type || "text";
  this.id = options.id || "";
  this.value = options.value || "";
  this.init();
}
inheritClass(Input, Container);
Input.prototype.init = function () {
  this.element = document.createElement('input');
  this.element.type = this.type;
  this.element.id = this.id;
  this.element.value = this.value;
}
/* -------------举例------------- */
let form = new Form({
  action: '/aaa.html',
  method: 'get',
  id: "myForm",
  parentNode: document.body
})
/* 三个div */
let user = new Div({ class: "form-line" })
  .add(new Label({ for: 'user', innerText: "用户名" }))
  .add(new Input({ type: "text", id: "user", name: "user" }));
let pwd = new Div({ class: "form-line" })
  .add(new Label({ for: 'pwd', innerText: "密码" }))
  .add(new Input({ type: "password", id: "pwd", name: "pwd" }));
let sub = new Div({ class: "form-line" })
  .add(new Input({ type: "submit", id: "sub", value: "登录" }));
/* 加入 */
form.add(user).add(pwd).add(sub);
form.show();

7. 观察者模式

作用:一对多的关系,每当主体发生改变,订阅过它的个体将会收到通知

let msgCenter = (function () {
  let events = {};
  return {
    /* 注册事件 */
    register(type, fn) {
      if (events[type]) {
        events[type].push(fn);
      } else {
        events[type] = [fn];
      }
    },
    /* 发布事件 */
    fire(type, info) {
      if (events[type]) {
        events[type].forEach(fn => fn(info));
      }
    },
    /* 取消事件 */
    cancle(type, fn) {
      if (events[type]) {
        let index = events[type].indexOf(fn);
        if (index !== -1)
          events[type].splice(index, 1);
      }
    }
  }
})();

function Person() {
  this.alreadyRegister = {};
}
Person.prototype.register = function (type, fn) {
  msgCenter.register(type, fn);
  this.alreadyRegister[type] = fn;
}
Person.prototype.cancleEvent = function (type) {
  let fn = this.alreadyRegister[type];
  if (fn) {
    msgCenter.cancle(type, fn);
    delete fn;
  }
}
// 举例
let person1 = new Person();
person1.register('news', (info) => {
  console.log(`person1收到news,内容是 ${info}`)
});
let person2 = new Person();
person2.register('news', (info) => {
  console.log(`person2收到news,内容是 ${info}`)
});
msgCenter.fire('news', 'testNews');
// person1收到news,内容是 testNews
// person2收到news,内容是 testNews
person1.cancleEvent('news');
msgCenter.fire('news', 'testNews2');
//person2收到news,内容是 testNews2

8. 策略模式

将所有的策略封装在一起,只给外部暴露出必要接口

<body>
  <label for="phone">手机号</label>
  <input type="text" id="input">
  <script>
    /* 策略 */
    let strategy = (function () {
      let _strategy = {
        isEmpty(val) {
          return val.length ? '' : '请输入手机号';
        },
        isPhone(val) {
          return /^1[3-9][0-9]{9}/.test(val) ? '' : '请输入正确的手机号';
        }
      };
      return {
        validate(type, val) {
          val = val.replace(/^\s+|\s+$/g, '');
          return _strategy[type] ? _strategy[type](val) : '无该验证方法';
        }
      }
    })();
    // 验证输入框
    input.onchange = function () {
      let val = input.value;
      let res = strategy.validate('isEmpty', val) || strategy.validate('isPhone', val) || '验证通过';
      console.log(res);
    }
  </script>
</body>

9. 链模式

作用:通过返回自身的方式实现链式调用

let obj = {
  a() {
    console.log('aaa');
    return this;
  },
  b() {
    console.log('bbb');
    return this;
  }
};
// 调用
obj.a().b().a().b();

10. 代理模式

作用:多个对象处理同一事件时,可以将这个事件交给另一个对象统一处理

<body>
  <ul id="ul">
    <li>1</li>
    <li>2</li>
  </ul>
  <script>
    /* 点击每个li都会打印li内容 */
    ul.onclick = function (e) {
      if (e.target.nodeName.toLowerCase() === 'li') {
        // 打印li内容
        console.log(e.target.innerHTML);
      }
    }
    // 新增的li也适用
    let newLi = document.createElement('li');
    newLi.innerHTML = '3';
    ul.appendChild(newLi);
  </script>
</body>

11. 访问者模式

作用:在不改变各元素的类的前提下定义作用于这些元素的新操作,将每一个类中的相关操作提取出来,包装成一个独立的对象,这个对象我们就称为访问者

let Visitor = (function () {
  return {
    splice() {
      return Array.prototype.splice.call(...arguments);
    },
    push() {
      return Array.prototype.push.call(...arguments);
    }
  }
})();
let obj = {};
Visitor.push(obj, 1)
Visitor.push(obj, 2);
console.log(obj);// { '0': 1, '1': 2, length: 2 }
Visitor.splice(obj, 0, 1);
console.log(obj);// { '0': 2, length: 1 }

12. 等待者模式

作用:通过多个异步进程监听,来触发未来发生的动作。

function Waiter() {
  this.dfds = [];
  this.doneArr = [];
  this.failArr = [];
  this.deferred = function () {
    return new Promise(this);
  }
}
Waiter.prototype = {
  when(...fns) {
    fns.forEach(fn => this.dfds.push(fn()));
    return this;
  },
  done(...fns) {
    this.doneArr = this.doneArr.concat(fns);
    return this;
  },
  fail(...fns) {
    this.failArr = this.failArr.concat(fns);
    return this;
  }
}
function Promise() {
  this.resolved = false;
  this.rejected = false;
  this.waiter = waiter;
}
Promise.prototype = {
  resolve() {
    this.resolved = true;
    /* 过滤已完成 */
    this.waiter.dfds = this.waiter.dfds.filter(v => v.resolved === false);
    /* 还有未完成则返回*/
    if (this.waiter.dfds.length) return;
    /* 全部执行完毕执行done回调 */
    this.waiter.doneArr.forEach(fn => fn());
  },
  reject() {
    this.rejected = true;
    this.waiter.dfds.splice(0);// 删除所有Promise对象
    this.waiter.failArr.forEach(fn => fn());// 执行所有失败回调
  }
}

// 举例
let waiter = new Waiter();
function fn1() {
  let dfd = waiter.deferred();
  setTimeout(function () {
    console.log("fn1 ok");
    dfd.resolve();
  }, 1000);
  return dfd;// 返回Promise
}
function fn2() {
  let dfd = waiter.deferred();
  setTimeout(function () {
    console.log("fn2 fail");
    dfd.reject();
  }, 1000 * 2);
  return dfd;
}
waiter.when(fn1, fn2).done(function () {
  console.log("done1");
}).done(function () {
  console.log("done2");
}).fail(function () {
  console.log('fail');
})
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值