设计模式之迭代器模式(6)

130 阅读2分钟

1、迭代器模式

1、介绍 image.png

2、使用 image.png

  • 结果

image.png

  • 如何将 这三个方法 封装到一起 作为一个迭代器的方式 ?

image.png

image.png

3、UML 类图

image.png

image.png

  • 代码实现
  class Iterator {
      constructor(container) {
        this.list = container.list;
        this.index = 0;
      }

      Next() {
        // 如果下一项存在 index++
        if (this.hasNext()) {
          return this.list[this.index++];
        }
        return null;
      }
      hasNext() {
        // 超出数组长度遍历到头了 返回 false
        if (this.index >= this.list.length) {
          return false;
        }
        return true;
      }
    }

    class Container {
      constructor(list) {
        this.list = list;
      }

      // 生成遍历器 并将 container(this) 传入
      getIterator() {
        return new Iterator(this);
      }
    }

    // 测试代码
    let arr = [1, 2, 3, 4, 5];
    const container = new Container(arr);
    const iterator = container.getIterator();
    while (iterator.hasNext()) {
      console.log(iterator.Next());
    }
  • 结果展示

image.png

  • 分明使用 Array.forEach 可解 为啥需要使用 这个 ?

  • 因为 之后会写兼容 所有有序的集合 非常强大

4、应用场景

image.png

image.png

image.png

image.png

image.png

  • 代码展示
    function each(data) {
    // 生成遍历器
      let iterator = data[Symbol.iterator]();

      let item = { done: false };
      while (!item.done) {
        item = iterator.next();
        if (!iterator.done) {
          console.log(item.value);
        }
      }
    }

    // 测试
    const arr = [1, 2, 3, 4, 5];
    const nodeList = document.getElementsByTagName("p");
    const m = new Map();
    m.set("a", 100);
    m.set("b", 200);

    each(arr);
    each(nodeList);
    each(m);
  • 结果展示

image.png

  • 能否简化

image.png

image.png

image.png

image.png

image.png

image.png

image.png

2、状态模式

1、介绍 image.png

image.png

image.png

  • 代码展示
 // 状态 控制 红灯 红灯 绿灯
    class State {
      constructor(color) {
        this.color = color;
      }

      // context 是 Context 的一个实例
      handle(context) {
        console.log(`turn to ${this.color} light`);
        // 设置状态
        context.setState(this);
      }
    }

    // 主体部分
    class Context {
      constructor() {
        this.state = null;
      }

      // 获取状态
      getState() {
        return this.state;
      }

      setState(state) {
        this.state = state;
      }
    }

    // 测试
    const context = new Context();
    const green = new State("green");
    const yellow = new State("yellow");
    const red = new State("red");

    // 绿灯亮了
    green.handle(context);
    console.log(context.getState());
    // 黄灯亮了
    yellow.handle(context);
    console.log(context.getState());
    // 红灯亮了
    red.handle(context);
    console.log(context.getState());
  • 结果展示

image.png

2、场景 展示

image.png

1、有限状态机

image.png

image.png

  • 代码展示

  • 要先安装 yarn add javascript-state-machine --save

  • 为了方便 安装 yarn add jquery --save

  • index.html 中需要一个 button id="btn1"

import StateMachine from "javascript-state-machine";
import $ from "jquery";

// 定义状态机
let fsm = new StateMachine({
  init: "收藏",
  transitions: [
    {
      name: "doStore",
      form: "收藏",
      to: "取消收藏",
    },
    {
      name: "deleteStore",
      form: "取消收藏",
      to: "收藏",
    },
  ],
  methods: {
    // 监听执行收藏
    onDoStore: function () {
      alert("收藏成功"); // 实际业务中此处 可发 post 请求
      updateText();
    },

    // 监听执行收藏
    onDeleteStore: function () {
      alert("取消收藏成功"); // 实际业务中此处 可发 post 请求
      updateText();
    },
  },
});

let $btn = $("#btn1");

//按钮点击事件
$btn.click(function () {
  if (fsm.is("收藏")) {
    fsm.doStore();
  } else {
    fsm.deleteStore();
  }
});

// 更新 文案
function updateText() {
  $btn.text(fsm.state);
}

// 初始化文案
updateText();
  • 结果展示 成功实现状态 改变 非常 nice 非常好 !

image.png

image.png

2、写一个 promise

image.png

image.png

image.png

  • 代码展示 (这个有点多 不过不困难)
import StateMachine from "javascript-state-machine";

// 状态机模型
let fsm = new StateMachine({
  init: "pending", // 初始化状态
  transitions: [
    // 两个转变的状态
    {
      name: "resolve", // 事件名称
      from: "pending",
      to: "fullfilled",
    },
    {
      name: "reject", // 事件名称
      from: "pending",
      to: "rejected",
    },
  ],
  methods: {
    // 监听 resolve
    onResolve: function (state, data) {
      // state 当前状态机实例  data fsm.resolve(xxx)传递的参数
      data.successList.forEach((fn) => fn());
    },
    onReject: function (state, data) {
      // state 当前状态机实例  data fsm.reject(xxx)传递的参数
      data.failList.forEach((fn) => fn());
    },
  },
});

// 写 promise
class MyPromise {
  constructor(fn) {
    this.successList = [];
    this.failList = [];

    fn(
      function () {
        // 调用状态机内的 resolve 实现状态变化
        fsm.resolve(this);
      },
      function () {
        // 调用状态机内的 reject 实现状态变化
        fsm.reject(this);
      }
    );
  }

  then(successFn, failFn) {
    this.successList.push(successFn);
    this.failList.push(failFn);
  }
}

// 测试代码 由这个熟悉的测试代码 实现promise

function loadImg(src) {
  const promise = new MyPromise(function (resolve, reject) {
    let img = document.createElement("img");
    img.inload = function () {
      resolve(img);
    };
    img.onerror = function () {
      reject();
    };
    img.src = src;
  });
  return promise;
}

let src = "xxx";
let result = loadImg(src);

result.then(
  function () {
    console.log("ok1");
  },
  function () {
    console.log("fail1");
  }
);

result.then(
  function () {
    console.log("ok2");
  },
  function () {
    console.log("fail2");
  }
);
  • 结果展示

image.png

image.png