设计模式的定义: 在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案。
设计模式并不能直接用来完成代码的编写,而是描述在各种不同情况下,要怎么解决问题的一种方案,它不是一个死的机制,它是一种思想,一种代码的形式。
每种语言对于各种设计模式都要它们自己的实现方式,对于某些设计模式来说,可能在某些语言下并不适用,比如工厂模式就不适用于JavaSctipt
。模式应该用在正确的地方,而所谓正确的地方只有我们深刻理解模式的意图后,再结合项目的实际场景才知道。
观察者模式定义了对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都将得到通知,并自动更新。
观察者模式属于行为模式,行为模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯。
观察者模式还有一个别名叫“发布-订阅模式”,又或者“订阅-发布模式”,订阅者和订阅目标是联系在一起的,当订阅目标发生改变时,逐各通知订阅者。
我们用报纸期刊的订阅来举例说明,当你订阅一份报纸,每天都会有一份最新的报纸送到你手上,有多少人订阅报纸,报社就会发多少份报纸,报社和订报纸的客户就是定义里描述的“一对多”的依赖关系。
其实24种基本设计模式中,并没有发布-订阅模式,上面也解释了,它只是观察者模式的一个别称。但经过时间的沉淀,它已经强大起来,已经独立于观察者模式,成为一种新的设计模式。
在现在的发布-订阅模式中,发布者的消息不会直接发送给订阅者,这意味着发布者和订阅者都不知道彼此的存在。在发布者和订阅者之间存在第三个组件,称为消息代理或调度中心或中间件,它维持着发布者和订阅者之间的联系,过滤所有发布者传入的消息,并相应的分发给它们的订阅者。
举个例子,你在微博上关注了A,同时其他很多人也关注了A,当A发布动态时,微博就会为你们推送这条动态。A就是发布者,你就是订阅者,微博是调度中心,你和A是没有直接的消息往来的,全是通过微博来协调的。
我们先来看下者两个模式的实现结构:
观察者模式: 观察者(Observer)直接订阅(Subscribe)主体(Subject),而当主体被激活时,会触发(Fire Event)观察者里的事件。
发布-订阅模式: 订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Topic),当发布者(Publisher)发布该事件(Publish topic)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。
// 有一家猎人公会,其中每个猎人都具体发布任务(publish),订阅任务(subscribe)的功能
// 它们都有一个订阅列表记录谁订阅了自己
// 定义一个猎人,包括姓名、级别、订阅列表
function Hunter(name, level) {
this,name = name
this.level = level
this.list = []
}
Hunter.prototype.publish = function (money) {
console.log(this,level + '猎人: ' + this.name + '寻求帮助')
this.list.forEach(function (callback) {
callback && callback(money)
})
}
Hunter.prototype.subscribe = function (target, callback) {
console.log(this.level + '猎人: ' + this.name + '订阅了: ' + target.name)
target.list.push(callback)
}
// 猎人公会走注册了几个猎人
var hunterZhang = new Hunter('张三', '钻石')
var hunterLi = new Hunter('李四', '黄金')
var hunterWang = new Hunter('王五', '白银')
var hunterZhao = new Hunter('赵六', '青铜')
// 赵六等级较低,可能需要帮助,所以张三、李四、王五都订阅了赵六
hunterZhang.subscribe(hunterZhao, function (money) {
console.log('小明表示: ' + (money > 200 ? '' : '暂时很忙,不能') + '给予帮助')
})
hunterLi.subscribe(hunterZhao, function () {
console.log('李四表示: 给予帮助')
})
hunterWang.subscribe(hunterZhao, function () {
console.log('王五表示: 给予帮助')
})
// 赵六遇到困难,悬赏198寻求帮助
hunterZhao.publish(198)
// 猎人们(观察者)关联他们感兴趣的猎人(目标对象),如赵六,当赵六有困难时,会自动通知给他们(观察者)
// 定义了一家猎人公会
// 主要功能包含任务发布大厅(topics)、订阅任务(subscribe)、发布任务(publish)
var HunterUnion = {
type: 'hunt',
topics: Object.create(null),
subscribe: function (topic, callback) {
if (!this.topics[topic]) {
this.topics[topic] = []
}
this.topics[topic].push(callback)
},
publish: function (topic, money) {
if (!this.topics[topic]) {
return
}
for(var cb of this.topics[topic]) {
cb(money)
}
}
}
// 定义一个猎人类,包括姓名和级别
function Hunter(name, level) {
this.name = name
this.level = level
}
// 猎人可以在猎人公会发布、订阅任务
Hunter.prototype.subscribe = function (task, fn) {
console.log(this.level + '猎人: ' + this.name + '订阅了狩猎: ' + task + '的任务')
HunterUnion.subscribe(task, fn)
}
Hunter.prototype.publish = function (task, money) {
console.log(this.level + '猎人: ' + this.name + '发布了狩猎: ' + task + '的任务')
HunterUnion.publish(task, money)
}
//猎人工会注册了几个猎人
let hunterZhang = new Hunter('张三', '钻石')
let hunterLi = new Hunter('李四', '黄金')
let hunterWang = new Hunter('王五', '白银')
let hunterZhao = new Hunter('赵六', '青铜')
//张三,李四,王五分别订阅了狩猎tiger的任务
hunterZhang.subscribe('tiger', function(money){
console.log('张三表示:' + (money > 200 ? '' : '不') + '接取任务')
})
hunterLi.subscribe('tiger', function(money){
console.log('李四表示:接取任务')
})
hunterWang.subscribe('tiger', function(money){
console.log('王五表示:接取任务')
})
//赵六订阅了狩猎sheep的任务
hunterZhao.subscribe('sheep', function(money){
console.log('赵六表示:接取任务')
})
//赵六发布了狩猎tiger的任务
hunterZhao.publish('tiger', 198)
//猎人们发布(发布者)或订阅(观察者/订阅者)任务都是通过猎人工会(调度中心)关联起来的,他们没有直接的交流。
观察者模式和发布-订阅模式最大的区别: 发布-订阅模式有事件调度中心。
观察者模式由具体目标调度,每个被订阅的目标里面都需要有对观察者的处理,这种处理方式可能会造成代码的冗余。
发布-订阅模式中,统一由调度中进行处理,订阅者和发布者互不干扰,消除了发布者和订阅者之间的依赖。这样一方面实现了解耦,另一方面可以实现更加细粒度的控制。比如发布者发布了很多消息,但不是所有的订阅者都希望接收到,就可以在调度中心做一些处理,类似权限控制之类的。还可以做一些节流操作。
《JavaScript设计模式与开发实践》一书中说到分辨模式的关键是意图而不是结构。
如果以结构来分辨模式,发布-订阅模式比观察者模式多了一个调度中心,所以发布-订阅模式不同于观察者模式。
如果以意图来分辨模式,它们都实现了对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都将得到通知,并自动更新,那么它们就是同一种模式,发布-订阅模式是在观察者模式的基础上做了优化升级。
不过不管它们是不是同一个设计模式,它们的实现方式的确是有区别,我们在使用时应该根据应用场景来判断选择哪个。
单例模式是我们开发中一个非常典型的设计模式,js单例模式要保证全局只生成唯一实例,提供一个单一的访问入口,单例的对象不同于静态类,我们可以延迟单例对象的初始化,通常这种情况发生在我们需要等待加载创建单例的依赖。
工厂模式下的对象我们不能识别它的类型,由于typeof返回的都是object类型,不知道它是那个对象的实例。另外每次造人时都要创建一个独立的person的对象,会造成代码臃肿的情况。
建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象
主要涉及知识点: HTML与XHTML,HTML与XHTML的区别,DOCTYPE与DTD的概念,DTD的分类以及DOCTYPE的声明方式,标准模式(Standard Mode)和兼容模式(Quircks Mode),标准模式(Standard Mode)和兼容模式(Quircks Mode)的区别
JavaScript中常见的四种设计模式:工厂模式、单例模式、沙箱模式、发布者订阅模式
javascript 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。 策略模式利用组合,委托等技术和思想,有效的避免很多if条件语句,策略模式提供了开放-封闭原则,使代码更容易理解和扩展, 策略模式中的代码可以复用。
javascript观察者模式又叫发布订阅模式,观察者模式的好处:js观察者模式支持简单的广播通信,自动通知所有已经订阅过的对象。存在一种动态关联,增加了灵活性。目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。
熟悉 Vue 的都知道 方法methods、计算属性computed、观察者watcher 在 Vue 中有着非常重要的作用,有些时候我们实现一个功能的时候可以使用它们中任何一个都是可以的
我觉得聊一下我爱用的 JavaScript 设计模式应该很有意思。我是一步一步才定下来的,经过一段时间从各种来源吸收和适应直到达到一个能提供我所需的灵活性的模式。让我给你看看概览,然后再来看它是怎么形成的
在围绕设计模式的话题中,工厂这个词频繁出现,从 简单工厂 模式到 工厂方法 模式,再到 抽象工厂 模式。工厂名称含义是制造产品的工业场所,应用在面向对象中,顺理成章地成为了比较典型的创建型模式
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!