浅浅了解设计模式之四 | 行为型

1,070 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情

image.png

终于,最后一篇设计模式

备忘录模式

在不破坏对象封装的前提下,获得对象的内部状态,并在对象之外保存这个状态,这样就可以获得对象最初的保存的状态

  • 三个角色:发起人、备忘录、管理者
  • 拿git提交记录做例子
  • 备忘录相当于每次提交的提交记录
  • 发起人相当于每次提交的媒介,可以访问备忘录的信息,保存最新的备忘录
  • 管理者存储发起人每次的提交信息,当管理的仓库满的时候就需要清除仓库,才能继续保存
  class Record {
    constructor(commitMsg) {
      this.commitMsg = commitMsg || '默认提交msg'
    }
    getCommitMsg() {
      return this.commitMsg
    }
    setCommitMsg(commitMsg) {
      this.commitMsg = commitMsg
    }
  }
  class Current {
    constructor() {
      this.commitMsg = ""
    }
    getCommitMsg() {
      return this.commitMsg
    }
    setCommitMsg(commitMsg) {
      this.commitMsg = commitMsg
    }
    createRecord() {
      return new Record(this.commitMsg)
    }
    restoreRecord() {
      this.setBookName((new Record).getName())
    }
  }
  class Depository{
      constructor(){
          this.record = [];
          this.top = 0;
      }
      push(f){
          this.record[this.top] = f;
          if(this.top>=3){
              console.log("已达上限,不能储存 "+f.getCommitMsg());
              return false
          }else {
              console.log("储存了 "+f.getCommitMsg());
              this.top++;
              return true
          }
      }
      pop(){
          this.top--;
          let f = this.record[this.top];
          if(this.top <= 0){
              console.log("撤回最后一个 "+f.getCommitMsg())
          }else {
              console.log("撤回了 "+f.getCommitMsg())
          }
      }
  }
  function test() {
    let current = new Current();
    let depository = new Depository();
    current.setCommitMsg('提交信息1');
    depository.push(current.createRecord());

    current.setCommitMsg('提交信息2');
    depository.push(current.createRecord());

    current.setCommitMsg('提交信息3');
    depository.push(current.createRecord());

    current.setCommitMsg('提交信息4');
    depository.push(current.createRecord());

    depository.pop();

    current.setCommitMsg('提交信息4');
    depository.push(current.createRecord());
  }
  test();

策略模式

封装一系列的算法,使之可以复用

  let identity = {
    's': () => '学生',
    't': () => '老师',
    'p': () => '家长'
  }
  let calcId = (level) => {
    return identity[level]();
  }
  console.log(calcId('s')); // 学生
  console.log(calcId('t')); // 老师

模板方法模式

拓展子类,继承父类,实现父类的方法。就是继承的那一套东西

  class Food {
    constructor(name) {
      this.name = name
    }
    makeFood() {
      console.log('准备好锅碗调料');
    }
    eatFood() {
      console.log('摆上餐桌');
    }
  }
  class Fish extends Food {
    constructor(name) {
      super(name);
    }
    makeFood() {
      super.makeFood();
      console.log('煎十分钟');
    }
    eatFood() {
      super.eatFood();
      console.log('剔骨头');
    }
  }
  let f = new Fish('草鱼');
  f.makeFood();
  f.eatFood();

职责链模式

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

不停往下找,直到可以实现该请请求的对象为止

image.png

  const buy500 = (pay) => {
    if (pay >= 500) {
      console.log('满五百减200');
    } else {
      return 'next'
    }
  }
  const buy300 = (pay) => {
    if (pay >= 300) {
      console.log('满三百减100');
    } else {
      return 'next'
    }
  }
  const buy100 = (pay) => {
    if (pay >= 100) {
      console.log('满一百减20');
    } else {
      return 'next'
    }
  }
  const buy = (pay) => {
    console.log('无满减');
  }
  Function.prototype.after = function(fn) {
    const self = this;
    return function () {
      const result = self.apply(self, arguments)
      if (result === 'next') {
        return fn.apply(self, arguments)
      }
    }
  }
  const buyFun = buy500.after(buy300).after(buy100).after(buy);
  buyFun(600);  // 满五百减200
  buyFun(300);  // 满三百减100
  buyFun(150);  // 满一百减20
  buyFun(50);   // 无满减

命令模式

将方法的调用、请求或者操作封装到一个对象里面,外部就可以只需要输入命令给对象就可以执行函数了

  class Person {
    constructor() {

    }
    write() {
      console.log('write');
    }
    play() {
      console.log('play');
    }
    sing() {
      console.log('sing');
    }
    run (...args) {
      for(let i of args) {
        this[i]();
      }
      return this;
    }
  }
  (new Person()).run('play', 'write').run('sing');

参考:

# JavaScript 23 种设计模式之 22 备忘录模式

# js设计模式【详解】总目录——最常用的20种设计模式

# JavaScript 命令模式

设计模式就写到这,我也只是浅浅的摸了摸边而已。更多的还是阅读了其他文章。模式和模式之间有很多相似处,各有优劣处和应用场景,就是另一个大文章了。

那摩,完结,撒❀~