博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
javascript设计模式小结
阅读量:6213 次
发布时间:2019-06-21

本文共 12566 字,大约阅读时间需要 41 分钟。

最近终于看完买了很久的《Javascript设计模式与开发实践》,感觉还是受益匪浅的。 在这里做了一个简单的小结,将书上提到的设计模式尽量用自己的思路写出来,当然也是有所借鉴。书上的代码都是基于ES5的,本次小结会用到ES6来写。 感觉应该还是蛮多错漏的,欢迎指正。

单例模式(Singleton pattern)

确保一个类只有一个实例,并提供对该实例的全局访问。

function createSingleton(construct) {  let storage = null;  let handle = {    construct: function(trapTarget, argumentList) {      if (!storage) {        storage = new trapTarget(argumentList[0]);      }      return storage;    },  };  return new Proxy(construct, handle);}class Singleton {  constructor(params) {    this.val = params;  }  getVal() {    console.log(this.val);  }  setVal(params) {    this.val = params;  }}// runlet ProxySingleton = createSingleton(Singleton);let singletonObj_1 = new ProxySingleton(123);let singletonObj_2 = new ProxySingleton(456);console.log(singletonObj_1 === singletonObj_2); // true复制代码

策略模式(Strategy pattern)

指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。

const Strategy = {  A(params) {    console.log('Execute strategy A!', params);  },  B(params) {    console.log('Execute strategy B!', params);  },  C(params) {    console.log('Execute strategy C!', params);  },};const StrategyExecute = function(params) {  const { type, val } = params;  return Strategy[type](val);};// runStrategyExecute({ type: 'A', val: 123 });StrategyExecute({ type: 'B', val: 456 });StrategyExecute({ type: 'C', val: 789 });复制代码

代理模式(Proxy pattern)

为其他对象提供一个代理以控制对这个对象的访问。

let game = {  play() {    console.log('Play!');  },};let gameMachine = {  token: 0,  play: new Proxy(game.play, {    apply(proxyTag, proxyThis, args) {      if (proxyThis.token > 0) {        proxyThis.token--;        return Reflect.apply(proxyTag, proxyThis, args);      } else {        console.warn('No token!')      }    },  })};// rungameMachine.play(); // No token!gameMachine.token = 1;gameMachine.play(); //Play!gameMachine.play(); // No token!复制代码

迭代器模式(Iterator pattern)

提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。

// 迭代器function Iterator(params) {  // 创建迭代器  let iterator = params();  // 开始迭代  let stepResult = iterator.next();  if (!stepResult.done) {    // 定义下一步操作的方法,并执行    (function step() {      if (!stepResult.done) {        if (typeof stepResult.value === 'function') {          (async function() {            let stepResultData = await stepResult.value();            stepResult = iterator.next(stepResultData);            step();          })();        } else {          stepResult = iterator.next(stepResult.value);          step();        }      }    })();  }}// 迭代步骤function fetchData() {  // ajax get some data  return [    {      id: 1,      name: 'test1',    },    {      id: 2,      name: 'test2',    }  ];}function resolveData(params) {  // rebuild data  return params.map(item => item.name);}let iteratorList = function *() {  const apiData = yield fetchData();  const list = yield resolveData(apiData);  yield console.log(list);};// runIterator(iteratorList);复制代码

观察者模式(Observer pattern)

发布-订阅模式(Publish–subscribe pattern)

在对象间定义一个一对多的联系性,由此当一个对象改变了状态,所有其他相关的对象会被通知并且自动刷新。

let Event = {  _events: {},  on(event, fn) {    if (Array.isArray(event)) {      event.forEach((e) => { this.on(e, fn) });    } else {      (this._events[event] || (this._events[event] = [])).push(fn);    }  },  once(event, fn) {    function on () {      this.off(event, on);      fn.apply(this, arguments);    }    on.fn = fn;    this.on(event, on);  },  off(event, fn) {    if (!arguments.length) {      this._events = Object.create(null);      return true;    }    if (Array.isArray(event)) {      event.forEach((e) => { this.off(e, fn) });      return true;    }    let eventFns = this._events[event];    if (!eventFns) {      return false;    }    if (!fn) {      this._events[event] = null;      return true;    }    if (fn) {      let eventFn;      let len = eventFns.length;      while (len--) {        eventFn = eventFns[len];        if (eventFn === fn || eventFn.fn === fn) {          eventFns.splice(len, 1);          break;        }      }      return true;    }  },  emit(event) {    let eventFns = this._events[event];    if (eventFns) {      let [ , ...rest ] = arguments;      eventFns.forEach((fn) => {        try {          fn.apply(this, rest);        } catch (err) {          console.error(`Error: event handler for "${event}"`, err, this);        }      });    }  }};// runEvent.once('testEventBus', () => { console.log('Event had emitted.'); });Event.emit('testEventBus'); // Event had emitted.复制代码

命令模式(Command pattern)

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。

class FanMachine {  constructor() {    this._commands = [];  };  execute(command, ...rest) {    this._commands.push(command);    command.execute(...rest);  }}class Fan {  static turnOn() {    console.log('开启');  };  static turnOff() {    console.log('关闭');  };  static windSpeed(params) {    console.log('风速:', params);  };}class setCommand {  constructor(fn) {    this.execute = fn;  }}// runlet fanCommandTurnOn = new setCommand(Fan.turnOn);let fanCommandTurnOff = new setCommand(Fan.turnOff);let fanCommandWindSpeed = new setCommand(Fan.windSpeed);let fanMachine = new FanMachine();fanMachine.execute(fanCommandTurnOn); // 开启fanMachine.execute(fanCommandWindSpeed, 1); //风速:1fanMachine.execute(fanCommandWindSpeed, 2); //风速:2fanMachine.execute(fanCommandWindSpeed, 3); //风速:3fanMachine.execute(fanCommandTurnOff); // 关闭复制代码

组合模式(Composite pattern)

把多个对象组成树状结构来表示局部与整体,这样用户可以一样的对待单个对象和对象的组合。

class Composite {  constructor() {    this._commands = [];  }  add(command) {    this._commands.push(command);  }  execute() {    this._commands.forEach((command) => { command.execute(); })  }}let commandA = {  execute() {    console.log('Execute A!');  }};let commandB = {  execute() {    console.log('Execute B!');  }};let commandC = {  execute() {    console.log('Execute C!');  }};let commandD = new Composite();commandD.add(commandB);commandD.add(commandC);let commandCenter = new Composite();commandCenter.add(commandA);commandCenter.add(commandD);// runcommandCenter.execute();// Execute A! // Execute B! // Execute C! 复制代码

模板方法模式(Template method pattern)

模板方法模式准备一个抽象类,将部分逻辑以具体方法及具体构造子类的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先构建一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。

class MakeDrink {  constructor(name) {    this._drinkName = name;  }  boilWater() {    console.log('煮沸水');  }  pourInCup() {    console.log('加原料');  }  brew() {    console.log('冲泡');  }  addCondiments() {    console.log('加调料');  }  init() {    this.boilWater();    this.pourInCup();    this.brew();    this.addCondiments();  }}class MakeLemonTea extends MakeDrink {  pourInCup() {    console.log('加茶叶');  }  addCondiments() {    console.log('加柠檬和糖');  }}// runlet lemonTea = new MakeLemonTea('柠檬茶');lemonTea.init();// 煮沸水// 加茶叶// 冲泡// 加柠檬和糖复制代码

享元模式(Flyweight pattern)

通过共享以便有效的支持大量细颗粒对象。

// ...复制代码

职责链模式(Chain-of-responsibility Pattern)

为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。

class Chain {  constructor(fn) {    this._fn = fn;    this._next = null;  }  setNext(next) {    return this._next = next;  }  pass(...args) {    let ret = this._fn.apply(this, args);    if (ret === 'pass') {      return this._next && this._next.pass.apply(this._next, args);    }    return ret;  }  next(...args) {    return this._next && this._next.pass.apply(this._next, args);  }}let first = new Chain(function(params) {  console.log('first: ', params);  this.next(2);});let second = new Chain(function(params) {  console.log('second: ', params);  return 'pass';});let third = new Chain(function(params) {  console.log('third: ', params);  this.next(4);});let last = new Chain(function(params) {  console.log('last: ', params);  return false;});first.setNext(second).setNext(third).setNext(last);// runfirst.pass(1);// first:  1// second:  2// third:  2// last:  4复制代码

中介者模式(Mediator pattern)

包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用,从而使它们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用,保证这些作用可以彼此独立的变化。

// ...复制代码

装饰器(修饰)模式(Decorator Pattern)

向某个对象动态地添加更多的功能。修饰模式是除类继承外另一种扩展功能的方法。

class Decorator {  constructor(params) {    const {value, configurable, enumerable, writable} = params;    this.value = value && typeof value === 'function' ? value : null;    this.configurable = configurable || false;    this.enumerable = enumerable || false;    this.writable = writable || false;  }  static create(obj, prop, descriptor) {    if (descriptor.value && typeof descriptor.value === 'function') {      let origin = obj[prop];      delete obj[prop];      descriptor.value = descriptor.value(origin);      Object.defineProperty(obj, prop, descriptor);    }  }}let decoratorTest = {  name: 'test',  init() {    Decorator.create(this, 'func', new Decorator({      value: function (fn) {        return function () {          // do something before...          console.log('before!');          fn.apply(this, arguments);          // do something after...          console.log('after!');        }      }    }));    console.log('init.');  },  func(...params) {    console.log('decoratorTest: ', ...params);  },};// rundecoratorTest.func(123);decoratorTest.init();decoratorTest.func(456);// decoratorTest: 123// init.// begin!// decoratorTest: 456// end!复制代码

状态模式(State pattern)

class State {  constructor(params) {    return State.create(this, params)  }  setState(state) {    this.current = state;    this.storage.push(state);  }  next() {    const { name: currName, to: currTo } = this.main[this.current];    if (currTo) {      const nextName = this.main[currTo].name;      const {beforeLeave} = this.hock[currName];      const {beforeEnter, onMount} = this.hock[nextName];      if (beforeLeave) { beforeLeave(); }      this.setState(currTo);      if (beforeEnter) { beforeEnter(); }      if (onMount) { onMount(); }    }    return this.current;  }  previous() {    return this.goBack(1);  }  goBack(num) {    const storage = this.storage;    const len = storage.length;    if (len > 1) {      if (len > num) {        this.current = storage[len - num -1];        this.storage = storage.slice(0, len - num);      } else {        this.current = storage[0];        this.storage = [storage[0]];      }    }    return this.current;  }  reset() {    return this.goBack(this.storage.length - 1);  }  addHock(stateName, event, fn) {    this.hock[stateName][event] = fn;  }  on(stateName, fn) {    this.addHock(stateName, 'onMount', fn);  }  beforeEnter(stateName, fn) {    this.addHock(stateName, 'beforeEnter', fn);  }  beforeLeave(stateName, fn) {    this.addHock(stateName, 'beforeLeave', fn);  }  static create(_this, params) {    const { initial, transitions, methods } = params;    _this.current = initial;    _this.storage = [initial];    _this.main = {};    _this.hock = {};    transitions.forEach((e) => {      const { name, from, to } = e;      // main      _this.main[from] = {};      _this.main[from].name = name;      _this.main[from].to = to;      // hock      _this.hock[name] = {};      _this.hock[name].from = from;      _this.hock[name].to = to;      _this.hock[name].beforeEnter = methods[`beforeEnter${State._firstUpperCase(name)}`] || null;      _this.hock[name].onMount = methods[`on${State._firstUpperCase(name)}`] || null;      _this.hock[name].beforeLeave = methods[`beforeLeave${State._firstUpperCase(name)}`] || null;      // event      _this[name] = function () {        const currStateName = _this.main[this.current].name;        if (name !== currStateName) {          const { beforeLeave } = _this.hock[currStateName];          const { from, beforeEnter, onMount } = _this.hock[name];          if (beforeLeave) { beforeLeave(); }          _this.setState.call(_this, from);          if (beforeEnter) { beforeEnter(); }          if (onMount) { onMount(); }          return from;        } else {          return this.current;        }      }    });    return _this;  }  static _firstUpperCase(str) {    const [first, ...rest] = str;    return `${first.toUpperCase()}${rest.join('')}`;  }}const green = 'green';const yellow = 'yellow';const red = 'red';let fsm = new State({  initial: green,  transitions: [    {      name: 'greenLight',      from: green,      to: yellow,    },    {      name: 'yellowLight',      from: yellow,      to:red,    },    {      name: 'redLight',      from: red,      to: green,    },  ],  methods: {    onGreenLight() { console.log('绿灯'); },    onYellowLight() { console.log('黄灯'); },    onRedLight() { console.log('红灯'); },  }});// run// 初始化状态为 greenfsm.next(); // 黄灯fsm.next(); // 红灯fsm.next(); // 绿灯fsm.previous(); // return 'red'fsm.greenLight(); // 绿灯fsm.yellowLight(); // 黄灯fsm.redLight(); // 红灯复制代码

设配器模式(Adapter pattern)

将某个类的接口转换成客户端期望的另一个接口表示。适配器模式可以消除由于接口不匹配所造成的类兼容性问题。

// ...复制代码

转载地址:http://ztcja.baihongyu.com/

你可能感兴趣的文章
LDA-math-神奇的Gamma函数
查看>>
cocos2d-x注意事项(十)Lua发展飞机战争-4-创建主角
查看>>
[HIS] HIT行业常用名词及缩写定义
查看>>
Git 学习笔记--拉取远程分支到本地
查看>>
jquery插件layer
查看>>
[BI基础] 一些不得不了解的概念
查看>>
【转载】mvc3部署
查看>>
Pat(Advanced Level)Practice--1043(Is It a Binary Search Tree)
查看>>
(一)----使用HttpClient发送HTTP请求(通过get方法获取数据)
查看>>
spring security原理图及其解释
查看>>
Redis安全
查看>>
17秋 软件工程 团队第五次作业 Alpha Scrum9
查看>>
DIV和SPAN的区别
查看>>
Jodd
查看>>
处理 Windows 虚拟机的计划内维护通知
查看>>
redis资料收集
查看>>
CNN中的局部连接(Sparse Connectivity)和权值共享
查看>>
UNIX域套接字编程和socketpair 函数
查看>>
[LeetCode] Set Intersection Size At Least Two 设置交集大小至少为2
查看>>
Maven update project...后jdk变成1.5,update project后jdk版本改变
查看>>