1.单例设计模式
单例设计模式:
使用场景:
- 重复引入第三方库
- VueX全局状态管理
一个构造函数一生只能有一个实例,不管new多少次都是只有一个实例,单例模式核心代码:
function Person() {
this.name = "Jack";
}
let instance = null;
function SingleTon() {
if (!instance) {
instance = new Person();
}
return instance;
}
const p1 = SingleTon();
const p2 = SingleTon();
console.log(p1 === p2); //输出true
第一次调用singleton的时候,instance是null,执行new person给instance赋值。从此之后instance就是一个person实例
第二次调用singleTon的时候,此时instance是第一次new出来的实例,if条件不会执行了,返回的是第一次实例的地址
对单例设计模式的改造:
单例设计模式改造:需要把instance变量保存下来,singleton是一个函数,里面可以判断 可以返回,并且以闭包的形式返回。
const SingleTon = (function () {
// 这个变量因为在一个不会被销毁的函数执行空间里面,所以会一直存在
let instance = null;
function Person() {
this.name = "Jack";
}
return function singleTon() {
if (!instance) {
instance = new Person();
}
return instance;
};
})();
const p1 = SingleTon();
const p2 = SingleTon();
console.log(p1 === p2); //输出true
2观察者模式
概念:观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新。观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯。
举个例子:我们坐在教室里,老师是观察者,我们是被观察者,当被观察者触发一些条件时,观察者就会触发技能。
代码实例:
创建观察者类
class Observer {
// name身份
// fn技能
constructor(name, fn = () => {}) {
this.name = name;
this.fn = fn;
}
}
创建两个观察者
```js
const bzr = new Observer("班主任", () => {
console.log("叫家长");
});
const xz = new Observer("校长", () => {
console.log("把班主任找来");
});
创建被观察者
/**
*1.创建被观察者
* 属性,有自己的状态
* 队列:记录都有谁观察者自己 ,数组[]
* 方法,能够设置自己的状态。要触发这个方法改变状态
* 方法,添加观察者
*/
class Subject {
constructor(state) {
// 记录自己的状态
this.state = state;
// 数组,记录观察自己的人
this.Observers = [];
}
// 设置自己的状态
setState(state) {
this.state = state;
// 触发观察者的技能
this.Observers.forEach((item) => {
// 告诉观察者我改变了什么状态
// item就是一个一个对象
// 把每一个观察者的技能触发掉
item.fn();
});
}
// 添加观察者
addObserver(obs) {
// some()
// 数组去重
this.Observers = this.Observers.filter((item) => item !== obs);
this.Observers.push(obs);
}
// 删除观察者
delObserver(obj) {
this.Observers = this.Observers.filter((item) => item !== obj);
}
}
const xiaoming = new Subject("学习");
xiaoming.addObserver(bzr);
xiaoming.addObserver(xz);
xiaoming.setState("11111");
查看结果:
叫家长
把班主任找来
3.发布订阅模式
基本概念:发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。
订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel),当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。
有一个对象,有人一直看着他,当这个对象发生变化的时候,第三方通知这个看着的人,触发技能
代码:
class Observer {
constructor() {
this.message = {};
}
// 向消息队列里面添加内容
on(type, fn) {
// type是行为
// 行为发生的时候,要做的事情
// 计入消息队列
if (!this.message[type]) {
// 如果没有该事件,就创建一个该类型的新的消息队列
this.message[type] = [];
}
this.message[type].push(fn);
}
// 删除消息队列的内容
off(type, fn) {
// fn 不存在
if (!fn) {
// 直接把这个事件取消掉
delete this.message[type];
return;
}
// 没有订阅过该消息
if (!this.message[type]) {
return;
}
// 确实订阅过
this.message[type] = this.message[type].filter((item) => item !== fn);
}
// 触发消息队列
trigger(type) {
// 判断是否订阅过
if (!this.message[type]) {
return;
}
this.message[type].forEach((item) => {
// item就是每一个函数
item();
});
}
}
const person1 = new Observer();
person1.on("a", handlerA);
person1.on("a", handlerB);
person1.trigger("a");
function handlerA() {
console.log("A");
}
function handlerB() {
console.log("B");
}
4. 策略模式
策略,指的是可以实现目标的方案集合,在某些特定情况下,策略之间是可以相互替换的。
比如在外卖平台上的这些优惠。满减、会员和红包等,每一个大项优惠都具体包含了多个优惠方案。如满减活动中,可以同时有满28减18、满58减38等。会员包含普通会员、超级会员等。
每一个优惠方式下面的多个优惠方案,其实都是一个策略。这些策略之间是相互排斥、可替换的。并且是有一定的优先级顺序的。
- 一个问题解决多个解决方案: 不一定要用哪一个,而且还会继续增加多个方案
const calcPrice = (function () {
const sale = {
// 100 -10
"100_10": function (price) {
return (price -= 10);
},
//200 - 25
"200_25": function (price) {
return (price -= 25);
},
"80%": function (price) {
return (price *= 0.8);
},
};
// 计算价格
function calcPrice(price, type) {
// 判断对象里面有没有该折扣类型
if (!sale[type]) {
return "没有该折扣类型";
}
// 如果有就执行
const result = sale[type](price);
return result;
}
// 添加折扣
calcPrice.add = function (type, fn) {
// 专门用来添加折扣
// 判断该折扣是否存在
if (sale[type]) return "折扣已经存在";
// 添加该折扣
sale[type] = fn;
};
calcPrice.del = function (type) {
delete sale[type];
};
return calcPrice;
})();
calcPrice.add("70%", function (price) {
return (price *= 0.7);
});
const res = calcPrice(320, "100_10");
const res1 = calcPrice(320, "70%");
console.log("--------------------------------------");
calcPrice.del("70%");
const rest = calcPrice(320, "70%");
console.log(rest);