网站首页 > 技术文章 正文
观察者
- 发布&订阅
 - 一对多
 - 验证
 - 主题和观察者分离,不是主动触发而是被动监听,两者解耦
 - 符合开放封闭原则
 - 示例
 - 点餐,等餐
 - 场景
 
- 处理http请求;多进程通讯
 
- .then的多次调用
 
- 网页事件绑定
 - Promise
 - jQuery callbacks
 - -
 
- nodejs 自定义事件
 - vue watch
 - vue,react 生命周期触发
 
// 主题,接收状态变化,触发每个观察者
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)
nodejs
const EventEmitter = require('events').EventEmitter
// const emitter1 = new EventEmitter()
// emitter1.on('some', () => {
// // 监听 some 事件
// console.log('some event is occured 1')
// })
// emitter1.on('some', () => {
// // 监听 some 事件
// console.log('some event is occured 2')
// })
// // 触发 some 事件
// emitter1.emit('some')
// const emitter = new EventEmitter()
// emitter.on('sbowName', name => {
// console.log('event occured ', name)
// })
// emitter.emit('sbowName', 'zhangsan') // emit 时候可以传递参数过去
// 任何构造函数都可以继承 EventEmitter 的方法 on emit
class Dog extends EventEmitter {
 constructor(name) {
 super()
 this.name = name
 }
}
var simon = new Dog('simon')
simon.on('bark', function () {
 console.log(this.name, ' barked')
})
setInterval(() => {
 simon.emit('bark')
}, 500)
文件流式读取steam
var fs = require('fs')
var readStream = fs.createReadStream('./data/file1.txt') // 读取文件的 Stream
var length = 0
readStream.on('data', function (chunk) {
 length += chunk.toString().length
})
readStream.on('end', function () {
 console.log(length)
})
var readline = require('readline');
var fs = require('fs')
var rl = readline.createInterface({
 input: fs.createReadStream('./data/file1.txt')
});
var lineNum = 0
rl.on('line', function(line){
 lineNum++
});
rl.on('close', function() {
 console.log('lineNum', lineNum)
});
迭代器
- 顺序访问一个集合
 - 使用者无需知道集合的内部结构(封装)
 - 验证
 - 迭代器对象和目标对象分离
 - 迭代器将使用者与目标对象隔离开
 - 符合开放封闭原则
 - 场景
 - ES6语法中,有序集合的数据类型已经有很多
 - Array Map Set String TypedArray arguments NodeList
 - 需要有一个统一的遍历接口来遍历所有数据类型
 - (注意,object 不是有序集合,可以用Map代替)
 - 以上数据类型,都有[Symbol.iterator]属性
 - 属性值是函数,执行函数返回一个迭代器
 - 这个迭代器就有next 方法可顺序迭代子元素
 - 可运行Array.prototype[Symbol.iterator]来测试
 - Iterator的价值不限于上述几个类型的遍历
 - 还有Generator 函数的使用
 - 即只要返回的数据符合Iterator 接口的要求
 
- jQuery each
 - ES6 Iterator
 
- jquery
 
UML类图
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())
}
let arr = [1, 2, 3, 4]
let nodeList = document.getElementsByTagName('p')
let m = new Map()
m.set('a', 100)
m.set('b', 200)
// function each(data) {
// // 生成遍历器
// let iterator = data[Symbol.iterator]()
// // console.log(iterator.next()) // 有数据时返回 {value: 1, done: false}
// // console.log(iterator.next())
// // console.log(iterator.next())
// // console.log(iterator.next())
// // console.log(iterator.next()) // 没有数据时返回 {value: undefined, done: true}
// let item = {done: false}
// while (!item.done) {
// item = iterator.next()
// if (!item.done) {
// console.log(item.value)
// }
// }
// }
function each(data) {
 for (let item of data) {
 console.log(item)
 }
}
each(arr)
each(nodeList)
each(m)
状态模式
- 一个对象有状态变化
 - 每次状态变化都会触发一个逻辑
 - 不能总是用if…else来控制
 - 验证
 - 将状态对象和主题对象分离,状态的变化逻辑单独处理
 - 符合开放封闭原则
 - 示例
 - 交通信号灯不同颜色的变化
 - 场景
 - Promise 三种状态:pending fullfilled rejected
 - pending->fullflled 或者pending->rejected
 - 不能逆向变化
 - 有限个状态、以及在这些状态之间的变化
 - 如交通信号灯
 - 使用开源lib:javascript-state-machine
 
- 有限状态机
 - Promise
 
class State {
 constructor(color) {
 this.color = color
 }
 handle(context) {
 console.log(`turn to ${this.color} light`)
 context.setState(this)
 }
}
class Context {
 constructor() {
 this.state = null
 }
 setState(state) {
 this.state = state
 }
 getState() {
 return this.state
 }
}
// 测试代码
let context = new Context()
let greed = new State('greed')
let yellow = new State('yellow')
let red = new State('red')
// 绿灯亮了
greed.handle(context)
console.log(context.getState())
// 黄灯亮了
yellow.handle(context)
console.log(context.getState())
// 红灯亮了
red.handle(context)
console.log(context.getState())
状态机模型
// 状态机模型
 var fsm = new StateMachine({
 init: '收藏', // 初始状态,待收藏
 transitions: [
 {
 name: 'doStore', 
 from: '收藏',
 to: '取消收藏'
 },
 {
 name: 'deleteStore',
 from: '取消收藏',
 to: '收藏'
 }
 ],
 methods: {
 // 执行收藏
 onDoStore: function () {
 alert('收藏成功')
 updateText()
 },
 // 取消收藏
 onDeleteStore: function () {
 alert('已取消收藏')
 updateText()
 }
 }
 })
 var $btn = $('#btn')
 // 点击事件
 $btn.click(function () {
 if (fsm.is('收藏')) {
 fsm.doStore(1)
 } else {
 fsm.deleteStore()
 }
 })
 // 更新文案
 function updateText() {
 $btn.text(fsm.state)
 }
 // 初始化文案
 updateText()
作者:侠客岛的含笑
来源:慕课网,转载请后台联系
猜你喜欢
- 2024-10-02 nodejs中使用sqlite3数据库(nodejs连接mysql数据库)
 - 2024-10-02 NodeJS & Dapr Javascript SDK 官方使用指南
 - 2024-10-02 专门为前端工程师设计 Nodejs+React 实战开发区块链“慕课”DApp
 - 2024-10-02 若依nodejs全栈(四:用户列表增删改查接口的实现)
 - 2024-10-02 系统性学习(3) Node.js——手写 Events
 - 2024-10-02 完美支持Vue3,一个自带管理模板的Vue3开源组件库——vuestic
 - 2024-10-02 GitHub精选 | 后台权限管理系统(基于Node.js)
 - 2024-10-02 若依nodejs全栈(三:用户信息和路由接口的实现)
 - 2024-10-02 技术开发者应该如何构建小团队的微服务方案?
 - 2024-10-02 全局变量、事件绑定、缓存爆炸?Node.js内存泄漏问题分析
 
- 最近发表
 - 
- 聊一下 gRPC 的 C++ 异步编程_grpc 异步流模式
 - [原创首发]安全日志管理中心实战(3)——开源NIDS之suricata部署
 - 超详细手把手搭建在ubuntu系统的FFmpeg环境
 - Nginx运维之路(Docker多段构建新版本并增加第三方模
 - 92.1K小星星,一款开源免费的远程桌面,让你告别付费远程控制!
 - Go 人脸识别教程_piwigo人脸识别
 - 安卓手机安装Termux——搭建移动服务器
 - ubuntu 安装开发环境(c/c++ 15)_ubuntu安装c++编译器
 - Rust开发环境搭建指南:从安装到镜像配置的零坑实践
 - Windows系统安装VirtualBox构造本地Linux开发环境
 
 
- 标签列表
 - 
- cmd/c (90)
 - c++中::是什么意思 (84)
 - 标签用于 (71)
 - 主键只能有一个吗 (77)
 - c#console.writeline不显示 (95)
 - pythoncase语句 (88)
 - es6includes (74)
 - sqlset (76)
 - apt-getinstall-y (100)
 - node_modules怎么生成 (87)
 - chromepost (71)
 - flexdirection (73)
 - c++int转char (80)
 - mysqlany_value (79)
 - static函数和普通函数 (84)
 - el-date-picker开始日期早于结束日期 (76)
 - js判断是否是json字符串 (75)
 - c语言min函数头文件 (77)
 - asynccallback (87)
 - localstorage.removeitem (77)
 - vector线程安全吗 (73)
 - java (73)
 - js数组插入 (83)
 - mac安装java (72)
 - 无效的列索引 (74)
 
 
