[Design Pattern] Memento Pattern

// memento.js

import { TodoList } from "./classes.js";

export const TodoHistory = {
  history: [],
  push(state) {
    if (state) {
      // always push a new Set to avoid reference issues
      this.history.push(new Set([...state]));
    }
  },
  pop() {
    if (this.history.length > 1) {
      this.history.pop();
      return this.history.pop();
    }
  },
};

// Push new state into history when the list changes
const todoList = TodoList.getInstance();
todoList.addObserver(() => {
  TodoHistory.push(todoList.items);
});

We store the whole list into history array, when store the list, we need to save the copy to avoid reference issue.

 

Observer mixin:

export const observerMixin = {
  observers: new Set(),
  addObserver(obs) {
    this.observers.add(obs);
  },
  removeObserver(obs) {
    this.observers.delete(obs);
  },
  notify() {
    this.observers.forEach((obs) => obs());
  },
};

 

TodoList:

import { observerMixin } from "./mixin.js";

export class TodoItem {
  constructor(text) {
    this.text = text;
  }

  equals(other) {
    return this.text === other.text;
  }
}

class TodoList {
  #data = new Set();

  get items() {
    return this.#data;
  }

  /**
   * Singleton instance
   */
  static instance = null;
  static {
    this.instance = new TodoList();
  }
  static getInstance() {
    return this.instance;
  }

  constructor() {
    if (TodoList.instance) {
      throw new Error("Use TodoList.getInstance() to access the list");
    }
  }

  // behavior
  add(item) {
    const array = Array.from(this.#data);
    const todoExists = array.filter((t) => t.equals(item)).length > 0;
    if (!todoExists) {
      this.#data.add(item);
      this.notify();
    }
  }

  delete(text) {
    const array = Array.from(this.#data);
    const todoToDelete = array.filter((t) => t.text === text)[0];
    if (todoToDelete) {
      this.#data.delete(todoToDelete);
      this.notify();
    }
  }

  find(text) {
    const array = Array.from(this.#data);
    return array.find((t) => t.text === text);
  }

  replaceList(list) {
    this.#data = list;
    this.notify();
  }
}

/**Mixin */
Object.assign(TodoList.prototype, observerMixin);

export { TodoList };

 

posted @   Zhentiw  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2022-08-19 [Typescript] TS Monorepo setup
2021-08-19 [SAA + SAP] 30. More solution Architectures
2021-08-19 [Javascript] event.target.closest(selector)
2021-08-19 [Javascript] Object.is() vs ===
2020-08-19 [Machine Learning] Octave Vectorization
2020-08-19 [CSS] Use CSS Grid to create an asymmetric promo grid
2020-08-19 [Machine Learning] Octave Control Statements, for while if
点击右上角即可分享
微信分享提示