一、代理模式
- 代理模式,使用者无权访问目标对象,中间加代理,通过代理做授权和控制。
- 对于代理模式的理解,可以举一个例。比如如果广告商想找到明星进行演出,不会直接联系明星,而是联系明星的经纪人,通过经纪人,去与明星之间进行沟通。
- 对于代理模式的应用,在 ES6 中的 Proxy 中也比较常见。
- 代理模式的设计原则验证,代理类和目标类分离,隔离开目标类和使用者,符合开放封闭原则。
- 代理模式与适配器模式的比较:适配器模式是提供一个不同的接口,比如不同版本的插头。代理模式是提供一个一模一样的接口。
- 代理模式与装饰器模式的比较:装饰器模式是扩展功能,原有功能不变且可直接使用。代理模式是显示原有功能,但是经过限制或者阉割之后的。
代理模式的代码,如下所示:
// 明星
let star = {
name: '张XX',
age: 25,
phone: '13910733521'
}
// 经纪人
let agent = new Proxy(star, {
get: function (target, key) {
if (key === 'phone') {
// 返回经纪人自己的手机号
return '18611112222'
}
if (key === 'price') {
// 明星不报价,经纪人报价
return 120000
}
return target[key]
},
set: function (target, key, val) {
if (key === 'customPrice') {
if (val < 100000) {
// 最低 10w
throw new Error('价格太低')
} else {
target[key] = val
return true
}
}
}
})
// 主办方
console.log(agent.name)
console.log(agent.age)
console.log(agent.phone)
console.log(agent.price)
// 想自己提供报价(砍价,或者高价争抢)
agent.customPrice = 150000
// agent.customPrice = 90000 // 报错:价格太低
console.log('customPrice', agent.customPrice)
二、外观模式
- 外观模式,为子系统中的一组接口提供了一个高层的接口,使用者使用这个高层接口。
- 对于外观模式的理解,可以举例。比如在去医院看病,接待员去挂号、门诊、划价和取药。
- 外观模式的设计原则验证,不符合单一职责原则和开放封闭原则,因此谨慎使用,不可滥用。
三、观察者模式
- 观察者模式,发布和订阅,一对多。
- 对于观察者模式的理解,可以举例。比如在咖啡馆点好咖啡以后,就可以玩手机、打游戏等,点好之后坐等被叫。
- 对于观察者模式的应用场景,网页事件绑定,Promise,jQuery callbacks 和 nodejs 自定义事件等等。在
node.js 中,处理 http 请求,多进程通讯。vue 和 react 组件生命周期触发, vue watch 等。 - 观察者模式的设计原则验证,主题和观察者分离,不是主动触发而是被动监听,两者解耦,符合开放封闭原则。
观察者模式的代码,如下所示:
// 主题,接收状态变化,触发每个观察者
class Subject {
constructor() {
this.state = 0
this.observers = []
}
getState() {
return this.state
}
setState(state) {
this.state = state
this.notifyAllObservers()
}
attach(observer) {
this.observers.push(observer)
}
notifyAllObservers() {
this.observers.forEach(observer => {
observer.update()
})
}
}
// 观察者,等待被触发
class Observer {
constructor(name, subject) {
this.name = name
this.subject = subject
this.subject.attach(this)
}
update() {
console.log(`${this.name} update, state: ${this.subject.getState()}`)
}
}
// 测试代码
let s = new Subject()
let o1 = new Observer('o1', s)
let o2 = new Observer('o2', s)
let o3 = new Observer('o3', s)
s.setState(1)
s.setState(2)
s.setState(3)
四、迭代器模式
- 迭代器模式,顺序访问一个集合,使用者无需知道集合的内部结构和封装。
- 对于迭代器的应用场景,比如 jQuery each、ES6 Iterator 等等。
- ES6 Iterator 的存在原因是 ES6语法中,有序集合的数据类型已经有很多,需要有一个统一的遍历接口来遍历所有的数据类型。Object 不是有序集合,可以用 Map 代替。
- ES6 Iterator 具有 [Symbol.iterator] 属性,属性值是函数,执行函数返回一个迭代器。这个迭代器就有 next
方法可顺序迭代子元素,可以运行 Array.prototype[Symbol.iterator] 来测试。 - ES6 Iterator 与 Generator 的区别是 Iterator 的价值是不限于上述几个类型的遍历,还有 Generator
函数的使用。只要返回的数据符合 Iterator 接口的要求,就可以使用 Iterator 的语法,这就是迭代器模式。 - 迭代器模式的设计原则验证,迭代器对象和目标对象分离,迭代器将使用者与目标对象隔离开,符合开放封闭原则。
迭代器模式的代码,如下所示:
class Iterator {
constructor(conatiner) {
this.list = conatiner.list
this.index = 0
}
next() {
if (this.hasNext()) {
return this.list[this.index++]
}
return null
}
hasNext() {
if (this.index >= this.list.length) {
return false
}
return true
}
}
class Container {
constructor(list) {
this.list = list
}
// 生成遍历器
getIterator() {
return new Iterator(this)
}
}
// 测试代码
let container = new Container([1, 2, 3, 4, 5])
let iterator = container.getIterator()
while(iterator.hasNext()) {
console.log(iterator.next())
}
本文详细介绍了前端开发中常见的四种设计模式:代理模式,用于授权和控制访问;外观模式,提供一个高层接口简化子系统的使用;观察者模式,实现发布-订阅机制,广泛应用于事件绑定;以及迭代器模式,允许顺序访问集合而无需暴露其内部结构。每个模式都结合实例进行了深入讲解,并讨论了它们的设计原则和适用场景。
1335

被折叠的 条评论
为什么被折叠?



