js设计模式

js设计模式

单例模式

要实现一个标准的单例模式并不复杂,无非是用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象。

特点:
1.限制类只能有一个实例化对象,如果已经存在,则不创建实例
2.可以全局访问
3.执行很多次,保持唯一性

优点:
适用于单一对象,只生成一个对象实例,
避免频繁创建和销毁实例,减少内存占用。

**缺点:**不适用动态扩展对象,或需创建多个相似对象的场景。

写法一

const Person = (function () {
  function Person(name, age) {
    this.name = name
    this.age = age
  }

  let ins = null

  return (...rest) => {
    if (!ins) {
      ins = new Person(...rest)
    }
    return ins
  }
})()

const p1 = Person('xi', 23)
const p2 = Person('hh', 3)
console.log(p1)
console.log(p2)

写法二

let Singleton = function (name) {
  this.name = name;
  this.instance = null;
};


Singleton.prototype.getName = function () {
  alert(this.name);

};

Singleton.getInstance = function (name) {

  if (!this.instance) {
    this.instance = new Singleton(name);
  }

  return this.instance;
};


let a = Singleton.getInstance('sven1');
let b = Singleton.getInstance('sven2');

console.log(a)  // Singleton构造函数
console.log(b)  // Singleton构造函数
a.getName()  // sven1
b.getName()  // sven1

alert(a === b);    // true 

写法三

class Singleton {
    // 私有属性,外部无法直接访问
    #instance = null;
 
    // 私有方法,外部无法直接调用
    #constructor() {
        // 初始化代码
    }
 
    // 静态方法,用于获取实例
    static getInstance() {
        if (!this.#instance) {
            this.#instance = new Singleton();
            this.#constructor();
        }
        return this.#instance;
    }
}
 
// 获取单例实例
const instance = Singleton.getInstance();

了解保护数据结构内部元素

我们希望保护内部的元素,只有我们暴露出的方法才能修改内部结构。这对于模式非常重要

下划线命名约定

使用下划线命名约定来标记一个属性为私有属性

class Stack { 
  constructor() { 

    this._count = 0; 
    this._items = {}; 
  } 

} 

下划线命名约定就是在属性名称之前加上一个下划线(_)。不过这种方式只是一种约定,并
不能保护数据,而且只能依赖于使用我们代码的开发者所具备的常识。

用 ES6 的限定作用域Symbol 实现类
const _items = Symbol('stackItems'); 
class Stack { 

  constructor () { 
    this[_items] = []; 
  } 

  // 栈的方法 。。。
  push(e){
  ...
  }
}

这种方法创建了一个假的私有属性,因为 ES2015 新增的 Object.getOwnProperty-
Symbols 方法能够取到类里面声明的所有Symbols 属性。下面是一个破坏Stack 类的例子。

let objectSymbols = Object.getOwnPropertySymbols(stack); 

console.log(objectSymbols.length); // 输出1 
console.log(objectSymbols); // [Symbol()] 

console.log(objectSymbols[0]); // Symbol()
stack[objectSymbols[0]].push(1);
WeakMap 实现类

有一种数据类型可以确保属性是私有的,这就是 WeakMap。 WeakMap 可以存储键值对,其中键是对象,值可以是任意数据类型。

const items = new WeakMap(); // {1} 
 
class Stack { 

  constructor () { 
    items.set(this, []); // {2} 
  } 

  push(element){ 
    const s = items.get(this); // {3} 
    s.push(element); 

  } 
  pop(){ 
    const s = items.get(this); 

    const r = s.pop(); 
    return r; 
  } 

  // 其他方法 
} 

现在,items 在Stack 类里是真正的私有属性。采用这种方法,代码的可读性不强,而且在扩展该类时无法继承私有属性。鱼和熊掌不可兼得!

其他写法

// 使用私有静态属性和静态方法

class Singleton {
    // 私有静态属性,用于存储单例实例
    private static #instance = null;

    // 私有构造函数,防止外部通过new Singleton()创建实例
    private constructor() {
        // 初始化代码
    }

    // 静态方法,用于获取单例实例
    static getInstance() {
        // 如果实例不存在,则创建一个新实例
        if (!Singleton.#instance) {
            Singleton.#instance = new Singleton();
        }
        // 返回单例实例
        return Singleton.#instance;
    }
}

// 使用单例模式
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();

console.log(instance1 === instance2); // 输出: true





// 使用模块化的方式
// 由于ES6引入了模块化,我们可以利用模块的特性来实现单例模式。
// singleton.js
class Singleton {
    constructor() {
        // 初始化代码
    }

    // 其他方法...
}

// 导出单例实例
const instance = new Singleton();
export default instance;

// app.js
import singletonInstance from './singleton';

// singletonInstance 现在是 Singleton 类的一个实例




// 使用Symbol和WeakMap
// 在某些情况下,你可能想要基于某种参数创建不同的单例实例,可以使用Symbol和WeakMap来实现。
const SingletonSymbol = Symbol('SingletonSymbol');
const SingletonMap = new WeakMap();

class Singleton {
    constructor(key) {
        if (!SingletonMap.has(key)) {
            SingletonMap.set(key, this);
        }
        return SingletonMap.get(key);
    }
}

// 创建不同的单例实例
const instance1 = new Singleton(SingletonSymbol);
const instance2 = new Singleton(SingletonSymbol);

console.log(instance1 === instance2); // 输出: true

// 创建另一个基于不同Symbol的单例实例
const instance3 = new Singleton(Symbol('AnotherSymbol'));

console.log(instance1 === instance3); // 输出: false

原型模式

原型模式是用于创建对象的一种模式,
我们不需要知道这个对象的具体类型,
而是直接找到一个对象,通过克隆来创建个一模一样的对象。
(原型模式其实就是利用JavaScript特有的原型继承特性去创建对象的方式)

function Person() {
  this.schoole = '实验小学'
}

Person.prototype.getName = function() {
  console.log(this.name)
}

const p = new Person()
const p1 = Object.create(p)  // 创建一个对象p1,让p作为p1的原型
p1.name = '小明'
console.log(p) // Person {schoole: '实验小学'}
console.log(p1)  // Person {name: '小明'}

p.getName()  // undefined
p1.getName()  // 小明

const p2 = Object.create(p)
p2.name = '小红'
p2.getName() // 小红
console.log(p2) //  Person {name: '小明'}


工厂模式

1.简单工厂模式

2.工厂方法模式

3.抽象工厂模式

特点:

1.根据不同的输入返回不同类的实例

2.工厂方式的主要思想是将对象的创建与对象的实现分离

优点:

1.良好的封装,代码结构清晰

(访问者无需知道对象的创建流程,特别是创建比较复杂的情况下)

2.扩展性优良,通过工厂方法隔离了用户和创建流程隔态,符合开放封闭原则

3.解耦了高层逻辑和底层产品类,符合最少知识原则,不需要的就不要去交流

缺点:带来了额外的系统复杂度,增加了抽象性

工厂模式之简单工厂模式

function IPhone() {
  this.name = '苹果手机'
}

function HWPhone() {
  this.name = '华为'
}

function factory(phone) {
  switch (phone) {
    case "IPhone":
      return new IPhone()
    case "HWPhone":
      return new HWPhone()
    default:
      throw new Error('本工厂没有此品牌手机')

  }
}

const f1 = factory('IPhone')
console.log(f1)         // 苹果手机

const f2 = factory('HWPhone')
console.log(f2)     /// 华为

factory('ximiPhone')
console.log(f2)     // 本工厂没有此品牌手机

工厂模式之工厂方法模式

// 只需要关注新增的类,不用去修改工厂内部的方法

function Factory(phone) {
  if (this instanceof Factory && this[phone]) {  // 看是否在这个工厂里
    const n = new this[phone]()
    return n
  } else {
    console.log(`没有当前${phone}类型的手机`)
    return {}
    // 使用new 调用构造器时,还要注意一个问题,如果构造器显式地返回了一个object 类型的对象,那么此次运算结果最终会返回这个对象,而不是我们之前期待的this
  }
}

Factory.prototype.IPhone = function(){
  this.name = '苹果手机'
}

Factory.prototype.HWPhone = function() {
  this.name = '华为'
}

const f3 = new Factory('IPhone')
console.log(f3)         // 苹果手机


const f4 = new Factory('HWPhone')
console.log(f4)       // 华为

工厂模式之抽象工厂模式

抽象工厂模式是设计模式中最抽象的一个,也是唯一-种抽 象化创建模式
创建出来的不是一个真正的对象实例,而是一个类簇

// 工厂模式之抽象工厂模式

class Phone {
  constructor(type) {
    this.type = type
  }
}


class IPhone extends Phone {
  constructor(name) {
    super('IPhone')
    this.name = name
  }
}

class HWPhone extends Phone {
  constructor(name) {
    super('HWPhone')
    this.name = name
  }
}


function factory(type) {
  switch(type) {
    case 'IPhone': return IPhone
    case 'HWPhone': return HWPhone
    default: 
    throw new Error('本工厂没有此品牌手机')
  }
}


let HWPhoneClass = factory('HWPhone')
let IPhoneClass = factory('IPhone')
let XMPhoneClass = factory('XMPhone')

let f5 = new HWPhoneClass('华为')
console.log(f5)   // type: 'HWPhone', name: '华为'

let f6 = new HWPhoneClass('苹果')
console.log(f6)   // type: 'IPhone', name: '苹果'

console.log(XMPhoneClass)  // 报错

策略模式

**特点:**定义一系列的算法,将他们一个个封装起来,使他们直接可以相互替换

function validator(value) {
  if (!/\d+/.test(value)) {
    console.log('请输入数字')
  } else if (value === '' || !value) {
    console.log('不可为空')
  }
  // else if ...
  // 这种写法扩展很麻烦,要写很多的衣服,耦合度高
}

let rules = {
  isNumber: function(value) {
    if (!/\d+/.test(value)) {
          console.log('idNumber验证通过:', value)
        } else{
          console.log('请输入数字')
        }
  },
  required: function(value) {
    if (value === '' || !value) {
      console.log('不可为空')
    } else {
      console.log('required验证通过:', value)
    }
  }

}


function validator(value, rule) {
  if(rules[rule]) {
    rules[rule](value)
  }
}

validator('abc', 'isNumber')  // 请输入数字
validator('123', 'isNumber')  // isNumbe r验证通过: 123
validator(123, 'isNumber')     // isNumbe r验证通过: 123
validator(null, 'required')    // 不可为空

建造者模式

建造者模式(生成器模式)

建造者模式(Builder Pattern) 是一种创建型设计模式,

它的主要目的是将复杂对象的构建过程和表示分离,

使得相同的构建过程可以创建不同的表示。

1.产品(Product)

表示要构建的复杂对象,包含多个部分或属性。

2.建造者(Builder)

定义了构建复杂对象的接口,声明了构建各个部分的方法。

3.具体建造者(Concrete Builder)

实现了建造者接口,具体实现构建复杂对象的各个部分的方法,

以及返回构建完成的产品。

4.指挥者(Director) :

控制建造者的构建过程,

负责根据定的构建顺序 或逻辑来组织建造者的方法调用,

以构建出特定的产品。


// 产品
class Car {
  constructor() {
    this.parts = []
  }

  addPart(part) {
    this.parts.push(part)
  }
  showInfo() {
    console.Log("汽车组成:" + this.parts.join(", "))
  }
}


//建造者
class CarBuilder {
  constructor() {
    this.car = new Car()
  }
  buildEngine() {
    this.car.addPart("引擎")
  }
  buildTires() {
    this.car.addPart("轮胎")
  }
  buildInterior() {
    this.car.addPart("汽车配件")
  }
  getResult() {
    return this.car
  }
}


//指挥者
class CarManufacturer {
  constructor(builder) {
    this.builder = builder
  }
  constructCar() {
    this.builder.buildEngine()
    this.builder.buildTires()
    this.builder.buildInterior()
    return this.builder.getResult()
  }
}

//使用建造者模式构建复杂对象
const builder = new CarBuilder()
const manufacturer = new CarManufacturer (builder)
const car = manufacturer. constructCar()
car.showInfo()

桥接模式

1.桥接模式是种结构型设计模式, 旨在将抽象与实现分离,使它们可以独 立地变化。
2.桥接模式通过创建桥接来连接抽象和实现,从而允许它们可以独立地进行扩展。

function Toast(ani) {
  this.ani = ani;
}
Toast.prototype.show = function () {
  this.ani.show();
};
Toast.prototype.hide = function () {
  this.ani.hide();
};

function Message(ani) {
  this.ani = ani;
}
Message.prototype.show = function () {
  this.ani.show();
}
Message.prototype.hide = function () {
  this.ani.hide();
}


const Animations = {
  bounce: {
    show: () => {
      cogsole.Log("弹跳着出现");
    },
    hide: () => {
      console.Log("弹跳着消失");},
  },
  slide: {
    show: () => {
      console.log("滑动出现");
    },
    hide: () => {
      console.log("滑动出现");
    },
  }
};

const toast = new Toast(Animations.slide);
toast.show();  // 滑动出现
toast.hide();  // 滑动出现
const msg = new Message(Animations.bounce)
toast.show();  //  弹跳着出现
toast.hide();  // 弹跳着消失

外观模式

外观模式是一种结构型设计模式,

旨在为复杂系统提供一个简化的接口,

以便客户端可以更方便地使用系统。

外观模式通过创建一个高层接口(外观) 来隐藏系统的复杂性,

并将客户端与系统的组件解耦。


function drawCircle() {
  console.log("画一个圆形")
}

function drawRectangle() {
  console.Log("画一个矩形")
}

function drawTriangle() {
  console.log("画一个三角形")
}


function ShapeMaker() {
  this.drawCircle = drawCircle
  this.drawRectangle = drawRectangle
  this.drawTriangle = drawTriangle
}

const maker = new ShapeMaker( ) ;
console. log ( maker)
maker . drawCircle();

享元模式

1、享元模式是一种结构型设计模式,
旨在通过共享对象来有效地支持大量细粒度的对象。心
2、享元模式的目标是减少内存消耗和提高性能,
通过共享共同属性的对象,减少重复创建相似对象的开销。

// 图标享元 
function Icon(type) {
  this.type = type
}
Icon.prototype.draw = function (x, y) {
  console.log(`Drawing ${this.type} : icon at  (${x}, ${y})`);
}

// 图标享元工厂
function IconFactory() {
  this.icons = {}
}

IconFactory.prototype.getIcon = function (type) {
  if (!this.icons[type]) {
    this.icons[type] = new Icon(type)
  }
  return this.icons[type];
}

IconFactory.prototype.getIconCount = function () {
  return object.keys(this.icons).length;
}

//客户端代码
const iconFactory = new IconFactory();

//绘制多个图标
iconFactory.getIcon("heart").draw(10, 10)
iconFactory.getIcon("star").draw(20, 20);
iconFactory.getIcon("heart").draw(30, 30);
iconFactory.getIcon("circle").draw(40, 40);

console. log(`Total Icons: ${iconFactory. getIconCount()}`)

适配器模式

适配器模式是种结构型设计模式,
旨在将一个类的接口转换成另一个接口,
以满足不同类之间的兼容性需求。

function square(number) {
  return number * number
}

function squareString(str) {
  const number = parseInt(str)
  return square(number)
}

const input = ' 5 ';
const result = squareString(input)
console.log(result)

代理模式

代理模式是JavaScript设计模式中的一种结构型模式。
代理模式通过创建一个代理对象, 将客户端的请求转发给真实对象,从而控制对真实对象的访问。


//真实图片
function RealImage(filename) {
  this.filename = filename;
  this.LoadImage();
}

RealImage.prototype.loadImage = function () {
  console.log(`Loading image: ${this.filename}`);
  //模拟加载图片的耗时操作
};

RealImage.prototype.display = function () {
  console.log(`Displaying image: ${this.filename}`);
  //模拟加载图片的耗时操作
};

//代理图片
function ProxyImage(filename) {
  this.filename = filename;
  this.realImage = null;
}


ProxyImage.prototype.display = function () {
  if (!this.realImage) {
    this.realImage = new RealImage(this.filename);
  }
  this.realImage.display();
};

// 客户端代码
const image1 = new ProxyImage("image1.jpg");
const image2 = new ProxyImage("image2.jpg");

image1.display(); //实际上会触发RealImage 对象的创建和加载
image1.display(); //直接使用缓存的RealImage 对象
image2.display(); //实际上会触发Rea LImage对象的创建和加载

组合模式

1.组合模式是一种结构型设计模式,它允许你将对象组合成树形结构以表示"整体部分"的层次结构。
2.组合模式使得客户端可以以统一的方式处理单个对象和对象组合。

function Component(name) {
  this.name = name;
  this.children = []
}

Component.prototype.addChild = function (child) {
  this.children.push(child)
}

function processComponent(component) {
  console.log(component.name)
  component.children.forEach((child) => {
    processComponent(child)
  })
}

const root = new Component("Root");
const comp1 = new Component("component 1")
const comp2 = new Component("component 2")
const comp3 = new Component("component 3")

root.addChild(comp1)
root.addChild(comp2)
comp1.addChild(comp3)

processComponent(root)

装饰模式

1.装饰模式是JavaScript 设计模式中的一种结构型模式。
2.装饰模式允许你在不改变对象的结构的情况下,动态地为对象添加额外的功能。

//原始函数
function operation(x) {
  return x * 2;
}

//装饰器函数
function decorator(fn) {
  return function (x) {
    const result = fn(x);
    // 对原始函数的结果进行装饰
    return result + 10;
  };
}

//使用装饰器函数包装原始函数
const decoratedOperation = decorator(operation);

//客户端代码
const input = 5;
const result = decoratedOperation(input)
console.log(result); //输出20 (5 * 2 + 10)

发布-订阅模式

发布-订阅模式是一种行为型设计模式
它将发送者(发布者) 和接收者(订阅者)解耦。
在发布-订阅模式中,发布者将消息发送到一个中心调度器
(通常称为消息队列或事件总线)
订阅者通过订阅感兴趣的消息类型来接收并处理相应的消息。


// 创建事件总线对象
const eventBus = {
  topics: {},

  subscribe(topic, callback) {
    if (!this.topics[topic]) {
      this.topics[topic] = [] 
    }
    this.topics[topic].push(callback) 
  },
  publish(topic, data) {
    if (this.topics[topic]) {
      this.topics[topic].forEach((callback) => {
        callback(data) 
      }) 
    }
  }
}

//订阅者1
const subscriber1 = (data) => {
  console.log(`订阅者1接收到的数据: ${ data }`) 
} 

//订阅者2
const subscriber2 = (data) => {
  console.log(`订阅者2接收到的数据: ${ data }`) 
} 

//订阅者3
const subscriber3 = (data) => {
  console.log(`订阅者3接收到的数据: ${ data }`) 
} 

//订阅消息
eventBus.subscribe ("message", subscriber1)  
eventBus.subscribe ("'message", subscriber2)  
eventBus.subscribe ("message2", subscriber3)  

// 发布消息
eventBus.publish("message", "Hello, subscribers!") 
eventBus.publish("message2", "mg2") 

迭代器模式

迭代器模式是一种行为型设计模式,
用于提供一种顺序访问集合元素的方法,
而无需暴露集合的内部表示。
迭代器模式将遍历操作与集合对象分离,
使得可以独立地修改集合对象和遍历算法。

function eachFunc(arr, callback) {
  for (let i = 0; i < arr.length; i++) {
    callback(arr[i])
  }
}

let sum = 0
//奇数个数
let oddCount = 0
eachFunc([1, 2, 3], (item) => {
  sum = +item
  if (item % 2 === 1) {
    oddCount++
  }
});
console.Log("sum:", sum)
console.Log("奇数个数: ", oddCount)

模板方法模式

模板方法模式是种行为型设计模式,
把不变部分抽象到父类,再将另外一些可变的部分放到子类中去实现。


//模板类
class BasicInfo {
  //尺寸设置
  setSize() { }
  //颜色设置
  setCoLor() { }
  //信息展示
  showInfo() {
    this.setSize();
    this.setColor();
  }
}


//手机
class Phone extends BasicInfo {
  setSize() {
    console.Log("尺寸4寸、4.5寸、5寸、5.5寸");
  }
  setColor() {
    console.log("颜色:红、紫、蓝、粉红、绿");
  }
}



//鞋子
class Shoes extends BasicInfo {
  setSize() {
    console.Log("尺寸36、37、38、39");
  }
  setColor() {
    console.Log("颜色:米白色、蓝绿色");
  }
}


console.log("手机: ");
const phone = new Phone();
phone.showInfo();
console.log("---------------------");
console.log("鞋子: ");
const shoes = new Shoes();
shoes.showInfo();

状态模式

状态模式是一种行为型设计模式,
它允许对象在内部状态发生变化时改变其行为。
状态模式通过将不同的状态封装成独立的类,
并定义一个公共接口来统它们的行为
使得对象可以根据当前状态选择不同的行为。


//电灯状态接口
class LightState {
  constructor(light) {
    this.light = light
  }

  pressSwitch() {
    throw new Error("This method must be overridden")
  }
}


// 亮灯状态 
class OnState extends LightState {
  pressSwitch() {
    console.Log("关闭灯光")
    this.light.setState(new OffState(this.light))
  }
}


// 灭灯状态 
class OffState extends LightState {
  pressSwitch() {
    console.log("打开灯光")
    this.light.setState(new OnState(this.light))
  }
}


// 电灯控制器
class Light {
  constructor() {
    this.state = new OffState(this)
  }
  setState(state) {
    this.state = state
  }
  pressSwitch() {
    this.state.pressSwitch()
  }
}

// 使用状态模式控制电灯
const light = new Light();
light.pressSwitch() // 打开灯光
light.pressSwitch() //关闭灯光
light.pressSwitch() //打开灯光

命令模式

命令模式是一种行为型设计模式,
它将请求或操作封装成一个独立的对象,
从而使得可以参数化客户端对象与具体操作对象之间的调用。

//电灯
function Light() {
  this.on = function () {
    console.log("打开灯光");
  };
  this.off = function () {
    console.log("关闭灯光");
  };
}


// 打开灯光命令 
function LightOnCommand(light) {
  return function () {
    light.on();
  };
}
// 关闭灯光命令
function lightOffCommand(light) {
  return function () {
    light.off();
  };
}


// 遥控器
function RemoteControl() {
  this.setCommand = function (command) {
    this.command = command;
  };
  I
  this.pressButton = function () {
    this.command();
  };
}

//使用命令模式控制电灯
var light = new Light();
var lightOnCommand = lightOnCommand(light);
var lightOffCommand = lightOffCommand(light);

var remoteControl = new RemoteControl();
remoteControl.setCommand(lightOnCommand);
remoteControl.pressButton(); // 打开灯光
remoteControl.setCommand(lightOffCommand);
remoteControl.pressButton(); //关闭灯光

访问者模式

访问者模式是一种行为型设计模式,
用于在不修改被访问对象的前提下,
将新的操作逻辑应用于对象的元素。
访问者模式可以使用对象的动态分派特性和多态来实现。


// 具体的元素函数
function concreteELementA() {
  console.Log("具体元素A的操作A");
}

function concreteELementB() {
  console.log("具体元素B的操作B");
}


//访问者函数
function visitor(element) {
  if (element === concreteELementA) {
    element();
  } else if (element === concreteElementB) {
    element();
  }
}

//使用访问者模式
const elements = [concreteElementA, concreteElementB];
for (const element of elements) {
  visitor(element);
}

中介者模式

用于将多个对象之间的通信行为集中管理和控制,
通过将对象之间的直接交互改为通过中介者进行间接交互,
降低了对象之间的耦合性。


// 同事函数
function colleague(mediator) {

  function send(message) {
    mediator.send(message, this);
  }

  function notify(message) {
    console.log(`收到消息: ${message} `);
  }

  return {
    send,
    notify
  };
}


//中介者函数
function mediator() {
  let colleagueA = null;
  let colleagueB = null;

  function setColleagueA(colleague) {
    colleagueA = colleague;
  }

  function setColleagueB(colleague) {
    colleagueB = colleague;
  }

  function send(message, colleague) {
    if (colleague === colleagueA) {
      console.log("colleagueA发送消息,colleagueB接收");
      colleagueB.notify(message);
    } else if (colleague === colleagueB) {
      console.log("colleagueB发送消息,colleagueA接收");
      colleagueA.notify(message);
    }
  }

  return {
    setColleagueA,
    setColleagueB,
    send,
  };

}

//使用中介者模式
const mediator0bj = mediator();
const colleagueA = colleague(mediator0bj);
const colleagueB = colleague(mediator0bj);
mediator0bj.setColleagueA(colleagueA);
mediator0bj.setColleagueB(colleagueB);
colleagueA.send("Hello from colleagueA");
console.log(-"--------")
colleagueB.send("Hi from colleagueB");


备忘录模式

是一种行为型设计模式,
它用于在不破坏对象封装的前提下,
捕获和保存对象的内部状态,并在需要时恢复对象到之前的状态。

该模式常用于撤销操作或保存历史状态。


//备忘录对象
class Memento {
  constructor(state) {
    this.state = state;
  }

  getState() {
    return this.state;
  }
}

//原始对象
class Originator {
  constructor() {
    this.state = null;
  }
  setState(state) {
    this.state = state;
  }
  getState() {
    return this.state;
  }
  //创建备忘录
  createMemento() {
    return new Memento(this.state);
  }

  //恢复备忘录
  restoreMemento(memento) {
    this.state = memento.getState();
  }
}


//备忘录管理器
class Caretaker {
  constructor() {
    this.mementos = [];
  }

  //添加备忘录
  addMemento(memento) {
    this.mementos.push(memento);
  }

  //获取备忘录
  getMemento(index) {
    return this.mementos[index];
  }
}

// 原始对象实例
const originator = new Originator();
//备用录管理器实例
const caretaker = new Caretaker();


//给原始对象设置值
originator.setState("步骤1");
//原始对象可以在需要保存状态的时候创建备忘录,并将备忘录对象交给备忘录
caretaker.addMemento(originator.createMemento());
originator.setState("步骤2");
caretaker.addMemento(originator.createMemento());

originator.setState("步骤3");
caretaker.addMemento(originator.createMemento());

console.log("当前步骤:", originator.getState());

originator.restoreMemento(caretaker.getMemento(1));
console.log("恢复步骤:", originator.getState());
originator.restoreMemento(caretaker.getMemento(2));
console.log("恢复步骤:", originator.getState());

职责链模式

是一种行为型设计模式,它允许多个对象依次处理同一个请求,形成一个处理链。
当一个对象无法处理请求时,它会将请求传递给下一个对象,直到有一个对象能够处理为止。

// 购买申请 
class PurchaseRequest {
  constructor(amount, purpose) {
    this.amount = amount;
    this.purpose = purpose;
  }
}

// 抽象审批人
class Approver {
  setNextApprover(nextApprover) {
    this.nextApprover = nextApprover;
  }
  processRequest(purchaseRequest) { }
}

//具体审批人:经理
class Manager extends Approver {
  processRequest(purchaseRequest) {
    if (purchaseRequest.amount <= 1000) {
      console.log(`经理处理了购买申请,金额${purchaseRequest.amount}, 用于购买设备`)
    } else if (this.nextApprover) {
      this.nextApprover.processRequest(purchaseRequest);
    } else {
      console.log("没人能处理此审批! ");
    }
  }
}

//具体审批人:副总经理
class VicePresident extends Approver {
  processRequest(purchaseRequest) {
    if (purchaseRequest.amount <= 5000) {
      console.log(`副总经理处理了购买申请,金额${purchaseRequest.amount}`)
    } else if (this.nextApprover) {
      this.nextApprover.processRequest(purchaseRequest);
    } else {
      console.log("没人能处理此审批! ");
    }
  }
}

//具体审批人:总经理
class President extends Approver {
  processRequest(purchaseRequest) {
    if (purchaseRequest.amount <= 10000) {
      console.log(`总经理处理了购买申请,金额${purchaseRequest.amount}, 用于购买设备`);
    } else {
      console.log("此审批被退回! ");
    }
  }
}


//经理
const manager = new Manager();
//副总经理
const vicePresident = new VicePresident();
//总经理
const president = new President();
//经理下一个审批人是副总经理
manager.setNextApprover(vicePresident);
//副总经理下一个审批人是总经理
vicePresident.setNextApprover(president);
// 创建购买申请
const purchaseRequest1 = new PurchaseRequest(800, "办公用品")
const purchaseRequest2 = new PurchaseRequest(3000, "项目设备")
const purchaseRequest3 = new PurchaseRequest(15000, "新软件")
//处理购买申请,都从经理开始
manager.processRequest(purchaseRequest1);
manager.processRequest(purchaseRequest2);
manager.processRequest(purchaseRequest3);
  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值