工厂模式
将创建对象的具体逻辑封装在⼀个函数中,创建后返回这个对象,那么这个函数就可以被视为⼀个⼯⼚。
// 简单⼯⼚模式:只需要⼀个正确的参数,就可以获取到你所需要的对象,⽤于⽣成实例
// 比如对象工厂,函数工厂
function Animal(opts) {
var obj = new Object();
obj.color = opts.color;
obj.name = opts.name;
obj.getInfo = function () {
return "名称:" + obj.name + ", 颜⾊:" + obj.color;
};
return obj;
}
var cat = Animal({ name: "波斯猫", color: "⽩⾊" });
// ⼯⼚⽅法模式:本意是将实际创建对象的⼯作推迟到⼦类中,这样核⼼类就变成了抽象类,
// ⼯⼚⽅法只是⼀个实例化对象的⼯⼚,只做实例化对象这⼀件事情,⽤于⽣成实例
class User {
constructor(name = "", viewPage = []) {
if (new.target === User) {
throw new Error("抽象类不能实例化!");
}
this.name = name;
this.viewPage = viewPage;
}
}
class UserFactory extends User {
constructor(name, viewPage) {
super(name, viewPage); // 调⽤⽗类的constructor(name, viewPage),继承⽗类的this对象
}
}
// let user = new User(); // 不允许直接实例化
let userFactory = new UserFactory();
//抽象⼯⼚模式:并不直接⽣成实例,⽽是⽤于对产品类簇的创建
function getAbstractUserFactory(type) {
switch (type) {
case "wechat":
return UserOfWechat;
break;
case "qq":
return UserOfQq;
break;
case "weibo":
return UserOfWeibo;
break;
default:
throw new Error("参数错误, 可选参数:wechat、qq、weibo");
}
}
let WechatUserClass = getAbstractUserFactory("wechat");
let QqUserClass = getAbstractUserFactory("qq");
let WeiboUserClass = getAbstractUserFactory("weibo");
let wechatUser = new WechatUserClass("微信⼩李");
let qqUser = new QqUserClass("QQ⼩李");
let weiboUser = new WeiboUserClass("微博⼩李");
单例模式
保证⼀个类仅有⼀个实例,并提供⼀个访问它的全局访问点。
class Singleton {
static getInstance = (function () {
let instance;
return function () {
if (!instance) {
instance = new Singleton(...arguments);
}
return instance;
};
})();
constructor(name) {
this.name = name;
}
}
let s1 = Singleton.getInstance("lisi");
console.log(s1.name); //lisi
let s2 = Singleton.getInstance("san");
console.log(s1.name); //lisi
console.log(s1 === s2); // true
观察者模式
定义了对象间⼀对多的依赖关系,当⽬标对象的状态发⽣改变时,所有依赖它的对象都会得到通知。
// ⽬标者类
class Subject {
constructor() {
this.observers = []; // 观察者列表
}
// 添加
add(observer) {
this.observers.push(observer);
}
// 删除
remove(observer) {
let idx = this.observers.findIndex((item) => item === observer);
idx > -1 && this.observers.splice(idx, 1);
}
// 通知
notify() {
for (let observer of this.observers) {
observer.update();
}
}
}
// 观察者类
class Observer {
constructor(name) {
this.name = name;
}
// ⽬标对象更新时触发的回调
update() {
console.log(`⽬标者通知我更新了,我是:${this.name}`);
}
}
// 实例化⽬标者
let subject = new Subject();
// 实例化两个观察者
let obs1 = new Observer("前端开发者");
let obs2 = new Observer("后端开发者");
// 向⽬标者添加观察者
subject.add(obs1);
subject.add(obs2);
// ⽬标者通知更新
subject.notify();
// 输出:
// ⽬标者通知我更新了,我是前端开发者
// ⽬标者通知我更新了,我是后端开发者
发布订阅模式
实现了对象间多对多的依赖关系,通过事件中⼼管理多个事件。⽬标对象并不直接通知观察者,⽽是通过事件中⼼来派发通知。
// 事件中⼼
let pubSub = {
list: {}, // {onwork:[fn1,fn2],offwork:[fn1,fn2],launch:[fn1,fn2]}
subscribe: function (key, fn) {
// 订阅
if (!this.list[key]) {
this.list[key] = [];
}
this.list[key].push(fn);
},
publish: function (key, ...arg) {
// 发布
for (let fn of this.list[key]) {
fn.call(this, ...arg);
}
},
unSubscribe: function (key, fn) {
// 取消订阅
let fnList = this.list[key];
if (!fnList) return false;
if (!fn) {
// 不传⼊指定取消的订阅⽅法,则清空所有key下的订阅
fnList && (fnList.length = 0);
} else {
fnList.forEach((item, index) => {
if (item === fn) {
fnList.splice(index, 1);
}
});
}
},
};
// 订阅
pubSub.subscribe("onwork", (time) => {
console.log(`上班了:${time}`);
});
pubSub.subscribe("offwork", (time) => {
console.log(`下班了:${time}`);
});
pubSub.subscribe("launch", (time) => {
console.log(`吃饭了:${time}`);
});
// 发布
pubSub.publish("onwork", "9:00:00");
pubSub.publish("offwork", "18:00:00");
pubSub.publish("launch", "12:00:00");
// 取消订阅
pubSub.unSubscribe("onwork");
pubSub.publish("onwork", "9:00:00");
适配器模式
适配器⽤来解决两个接⼝不兼容的情况,不需要改变已有的接⼝,通过包装⼀层的⽅式实现两个接⼝的正常协作。
// 已有的地图接⼝
var googleMap = {
show: function () {
console.log("开始渲染⾕歌地图");
},
};
var baiduMap = {
display: function () {
console.log("开始渲染百度地图");
},
};
// 已有的渲染接⼝
var renderMap = function (map) {
if (map.show instanceof Function) {
map.show();
}
};
// 适配器
var baiduMapAdapter = {
show: function () {
return baiduMap.display();
},
};
renderMap(googleMap); // 开始渲染⾕歌地图
renderMap(baiduMapAdapter); // 开始渲染百度地图
代理模式
不直接引⽤另⼀个对象,通过代理对象间接引用,起到中介的作⽤。
var obj = {};
var proxy = new Proxy(obj, {
get: function (target, key, receiver) {
console.log(`getting ${key}!`);
return Reflect.get(target, key, receiver);
},
set: function (target, key, value, receiver) {
console.log(`setting ${key}=${value}!`);
return Reflect.set(target, key, value, receiver);
},
});
proxy.count = 1;
proxy.count;
装饰模式
不改变已有的函数,给函数添加额外的功能,⽐如ES7中的装饰器。