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);