开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情
行为型:多个对象之间互相配合,完成单个对象无法独立完成的任务
迭代器模式
迭代器很容易就想到遍历,可以迭代一个对象的内部元素而不暴露底层,for循环、map、foreach都属于迭代器模式
function each(arr, callback) {
for(let i in arr) {
callback(arr[i]);
}
}
each([1,2,3], (res) => {
console.log(res);
})
解释器模式
这种模式实现了一个表达式接口,该接口解释一个特定的上下文
大概是:小小的实现了接口的功能
class Parent {
constructor(name) {
this.name = name
}
getString() {
return this.name
}
}
class Son extends Parent {
constructor(name) {
super(name);
}
getString() {
return super.getString() + " say hi!";
}
}
let son = new Son('zhangsan');
console.log(son.getString()); // zhangsan say hi!
基础类实现基础功能,扩展类根据需要的业务对函数进行补充
观察者模式
// 餐饮老板 被观察者
class CateringOwner {
constructor() {
this.observers = [];
}
add(o) {
this.observers.push(o);
}
remove(o) {
this.observers.filter(item => item === o);
}
notify() {
console.log('老板炒糊了!!');
this.observers.forEach(item => {
item.go();
})
}
}
// 消费者 观察者
class Customer {
go() {
console.log('不吃啦,快跑!!');
}
}
let owner = new CateringOwner();
let c1 = new Customer();
let c2 = new Customer();
let c3 = new Customer();
owner.add(c1);
owner.add(c2);
owner.add(c3);
owner.notify();
这里,餐饮老板作为被观察者,为1,消费者作为观察者,为n,一旦餐饮老板把料理做糊了,这一行为就会通知到所有消费者,让消费者产生go的行为
观察者模式跟发布订阅模式类似,发布订阅是观察者模式的升级版
发布/订阅模式使用一个主题/事件频道,这个频道处于想要获取通知的订阅者和发起事件的发布者之间。这个事件系统允许代码定义应用相关的事件,这个事件可以传递特殊的参数,参数中包含有订阅者所需要的值。这种想法是为了避免订阅者和发布者之间的依赖性。
发布订阅者模式
// 餐饮老板 观察者
class CateringOwner {
constructor(name, takeaway) {
this.name = name;
this.takeaway = takeaway;
}
// 注册料理
addDish(dishName) {
this.takeaway.addDish(dishName);
}
// 推送料理
publishDish(dishName) {
this.takeaway.publishDish(dishName);
}
}
// 消费者 被观察者
class Customer {
constructor(name, takeaway) {
this.name = name;
this.takeaway = takeaway;
}
// 订阅料理
subscribeDish(dishName) {
this.takeaway.subscribeDish(dishName, this);
}
// 取消订阅
unSubscribrDish(dishName) {
this.takeaway.unSubscribrDish(dishName, this);
}
update(dish) {
console.log(this.name + '观察到 '+ dish + ' 变化了');
}
}
// 第三方
class Takeaway {
constructor() {
this.dishes = {}
}
// 餐厅在外卖平台上注册料理
addDish(dishName) {
this.dishes[dishName] = [];
}
// 餐厅在外卖平台上注销料理
removeDish(dishName) {
delete this.dishes[dishName];
}
// 消费者订阅料理
subscribeDish(dishName, sub) {
if (this.dishes[dishName]) {
this.dishes[dishName].push(sub);
}
}
// 消费者取消订阅料理
unSubscribrDish(dishName, sub) {
if (this.dishes[dishName]) {
this.dishes[dishName].forEach((item, index) => {
if (item === sub) {
this.dishes[dishName].splice(index, 1);
}
});
}
}
// 外卖平台下通知某种料理所有下消费者
publishDish(dishName) {
this.dishes[dishName].forEach(item => {
item.update(dishName);
})
}
}
let takeaway = new Takeaway();
// 餐馆
let xiaomai = new CateringOwner("小麦", takeaway);
// 餐馆提供这些料理(愿意暴露的属性)
xiaomai.addDish("汉堡包");
xiaomai.addDish("炸鸡腿");
xiaomai.addDish("薯条");
xiaomai.addDish("蛋挞");
// 顾客
let customer1 = new Customer('zhangsan', takeaway);
let customer2 = new Customer('lisi', takeaway);
let customer3 = new Customer('wangwu', takeaway);
// 顾客订阅这些料理(愿意观察的属性)
customer1.subscribeDish("汉堡包");
customer1.subscribeDish("炸鸡腿");
customer2.subscribeDish("炸鸡腿");
customer2.subscribeDish("薯条");
customer2.subscribeDish("蛋挞");
customer3.subscribeDish("汉堡包");
// 一旦餐馆有任意料理发生变动希望 有订阅该料理的顾客 知晓,就调用发布函数
xiaomai.publishDish("汉堡包");
xiaomai.publishDish("炸鸡腿");
xiaomai.publishDish("蛋挞");
xiaomai.publishDish("薯条");
// zhangsan观察到 汉堡包 变化了
// wangwu观察到 汉堡包 变化了
// zhangsan观察到 炸鸡腿 变化了
// lisi观察到 炸鸡腿 变化了
// lisi观察到 蛋挞 变化了
// lisi观察到 薯条 变化了
虽然这个例子有点离谱,但是这个意思就是这个意思,更好的例子可以阅读文尾的参考文章。
相当于中间商捆绑了订阅者和发布者的行为,发布者可以自由选择发布自己想要让别人知道的属性,订阅者也可以自由选择想要知道别人那些属性变化了。中间商也可以有更多的发布者。
中介模式
收集不同对象的信息,对这些信息进行处理
用一个中介对象来封装一系列的对象交互
let meditaor = (() => {
let sizes = ['s', 'm', 'l'];
let colors = ['red', 'yellow', 'blue'];
return {
validate: function(obj) {
if (sizes.indexOf(obj.size) < 0){
console.log('请选择尺码');
return;
}
if (colors.indexOf(obj.color) < 0){
console.log('请选择颜色');
return;
}
if (!obj.count){
console.log('数量要大于0');
return;
}
console.log('加入购物车');
}
}
})()
let form = {
validate: () => {
let obj = {
color: 'blue',
size: 'l',
count: 0
}
meditaor.validate(obj);
}
}
form.validate(); // 数量要大于0
访问者模式
访问者模式是将对数据的操作和数据结构进行分离,将对数据中各元素的操作封装成独立的类,使其在不改变数据结构的前提下可以拓展对数据新的操作。
五种结构:抽象访问者,具体访问者,抽象元素,具体元素,对象结构
抽象访问者:定义具体访问者的接口,具体访问者实现函数,确定在访问具体元素时需要做什么
抽象元素:定义具体元素的接口,具体元素实现函数,实现包含接收操作
对象结构:包含具体元素的数组,提供访问者去访问的接口
这里可以直接看文尾的文章举得例子(这个实在是太麻烦了叭)
状态模式
当一个对象的内部状态发生改变时,会导致其行为的改变,这看起来像是改变了对象。
let weatherFun = (() => {
let weather = null;
return {
change: (w) => {
weather = w;
weather.operate();
}
}
})();
function Sunny () {}
Sunny.prototype.operate = () => {
console.log('放风筝啦!');
}
function Rainy () {}
Rainy.prototype.operate = () => {
console.log('天要下雨,娘要嫁人');
}
function Snowy () {}
Snowy.prototype.operate = () => {
console.log('鹅毛大雪');
}
weatherFun.change(new Sunny())
weatherFun.change(new Rainy())
weatherFun.change(new Snowy())
// 放风筝啦!
// 天要下雨,娘要嫁人
// 鹅毛大雪
天气的状态变化会导致weatherFun产生不同的行为,看起来像是改变了对象
参考: