JavaScript设计模式读书笔记(三)=> 行为型设计模式
全系列目录
- JavaScript设计模式读书笔记(一)=> 创建型设计模式
- JavaScript设计模式读书笔记(二)=> 结构型设计模式
- JavaScript设计模式读书笔记(三)=> 行为型设计模式
- JavaScript设计模式读书笔记(四)=> 技巧型设计模式
- JavaScript设计模式读书笔记(五)=>架构型设计模式,MVC,MVP,MVVM
文章目录
1. 模板方法模式
父类定义一组操作骨架,而将一些实现步骤推迟到子类中。
这节自己没有想到很好用到生产中的例子
// e.g. const Alert = function (data) { this.content = data.content; this.panel = document.createElement('div'); this.panel.class = 'alert' // xxxxx } Alert.prototype.init = function () { // xxxx } const RightAlert = function (data) { Alert.call(this, data); this.panel.class = 'right-alert alert' } RightAlert.prototype = Object.create(Alert);
关于提示框的实现看了下antd的Model实现方法,它是如何实现多种类型的提示框之间代码复用的。
- 细粒度模块拆分,例如底部按钮,图标,样式等
- 通用提示框提前写好组件默认配置项
- 特殊提示框通过1步的细粒度模块拆分可以做到自由定制
2. 观察者模式
这个在如今貌似用的也挺多的。其又称作发布-订阅者模式或消息机制,定义了一种依赖关系,解决了主题对象与观察者之间的功能的耦合。
2.1. 创建一个观察者
它有一个消息容器和三个方法,分别是订阅消息方法,取消订阅的消息方法,发送订阅的消息方法。
const Observer = ( function() { const _message = {}; return { // 注册信息 regist: function(type, fn) { if (typeof _message[type] === 'undefined') { _message[type] = [fn]; } else { _message[type].push(fn); } }, // 发布信息 fire: function(type, args = {}) { if (!_message[type]) return const events = { type, args } for (let item of _message[type]) { item.call(this, events); } }, // 移除信息 remove: function(type, fn) { if (Array.isArray(_message[type])) { _message[type] = _message[type].filter(item => item !== fn) } } } } )() // ==========> 测试 Observer.regist('test', (e) => { console.log(e.type, e.args) }) Observer.fire('test', 'asdasdasd'); // test, asdasdasd
2.2. 对象之间解耦
看一个例子
const student = function(result) { this.result = result; this.say = () =>{ console.log(this.result); } } student.prototype.answer = function(question) { Observer.regist(question, this.say); } student.prototype.sleep = function(question) { console.log(`${this.result} ${question} 已被注销`); Observer.remove(question, this.say); } const teacher = function() {}; teacher.prototype.ask = function(question) { console.log('问题是 ' + question); Observer.fire(question); } const student1 = new student('1号回答问题'); const student2 = new student('2号回答问题'); student1.answer('快毕业了'); student1.answer('时间太快了'); student2.answer('快毕业了'); student2.answer('时间太快了'); student2.sleep('时间太快了'); const teacher1 = new teacher(); teacher1.ask('快毕业了'); teacher1.ask('时间太快了'); // ================> 输出 > "2号回答问题 时间太快了 已被注销" > "问题是 快毕业了" > "1号回答问题" > "2号回答问题" > "问题是 时间太快了" > "1号回答问题"
观察者模式最主要的作用是解决类或者对象之间的耦合,解耦两个相互依赖的对象,使其依赖于观察者的消息机制。
2.3. ES6 Reflect和Proxy实现观察者模式
此小节来自: http://es6.ruanyifeng.com/#docs/reflect#实例:使用-Proxy-实现观察者模式
使用 Proxy 写一个观察者模式的最简单实现,即实现observable和observe这两个函数。思路是observable函数返回一个原始对象的 Proxy 代理,拦截赋值操作,触发充当观察者的各个函数。
const queuedObservers = new Set(); const observe = fn => queuedObservers.add(fn); const observable = obj => new Proxy(obj, {set}); function set(target, key, value, receiver) { const result = Reflect.set(target, key, value, receiver); queuedObservers.forEach(observer => observer()); return result; }
上面代码中,先定义了一个Set集合,所有观察者函数都放进这个集合。然后,observable函数返回原始对象的代理,拦截赋值操作。拦截函数set之中,会自动执行所有观察者。
下面来看一个使用例子:
const person = observable({ name: '张三', age: 20 }); function print() { console.log(`${person.name}, ${person.age}`) } observe(print); person.name = '李四'; // 输出 // 李四, 20
3. 状态模式
状态模式是解决程序中臃肿的分支判断语句问题,最终的目的是简化分支判断流程,将每个分支转化为一种状态独立出来,方便每种状态的管理又不至于每次执行时遍历所有分支。
思路:创建一个内部状态变量,然后内部封装好每种动作对应的状态,最后状态对象返回一个接口对象,它可以对内部的状态修改或者调用。
const State = function () { const _current = {}; const states = { jump: function() { console.log('jump') }, move: function() { console.log('move'); } } const action = { changeState: function(...arg) { for (let item of arg) { _current[item] = true; } return this; }, goes: function() { console.log('触发了动作'); for (let prop in _current) { states[prop] && states[prop](); } return this; } } return { ...action } } const a = new State(); a.changeState('jump', 'move').goes().changeState('jump').goes()
4. 策略模式
策略模式从代码上来看和状态模式差不多,逻辑只是稍有不同。状态模式中对状态的控制来决定表现行为,所以状态之间通常是不能相互代替的,否则将产生不同的行为结果;策略模式核心是算法。
// e.g. const State = function () { const states = { phone: function(value) { return '判断是否是电话' }, number: function(value) { return '判断是否是数字' } } const action = { check: function(type, value) { return states[type] ? states[type](value) : '没有该类型的检测方法'; }, add: function(type, fn) { states[type] = fn; } } return { ...action } }
5. 命令模式
命令模式是将执行的命令封装,解决命令的发起者与命令的执行者之间的耦合。每一个命令实际上是一个操作。
const viewCommond = (function() { const action = { calculate: (value) => { console.log('复杂计算,执行一个操作 ' + value.a); } } function execute(msg) { action[msg.command].call(action, msg.param); } return execute })() viewCommond({ command: 'calculate', param: { a: 1 } })
6. 备忘录模式
它最主要的任务是对现有数据或者状态做缓存,为将来某一刻的使用或者回复做准备。
此处类似于现在的记忆化函数
// =================================》 第一种实现方法 来自《JavaScript权威指南》 function memoize(f) { var cache = {}; return function(){ var key = arguments.length + Array.prototype.join.call(arguments, ","); if (key in cache) { return cache[key] } else return cache[key] = f.apply(this, arguments) } } // =================================》 第一种实现方法 来自memoize-one // 代码地址 https://github.com/alexreardon/memoize-one/blob/master/src/index.js export function memoize (resultFn) { let lastArgs = []; // 用来存放上一次调用的参数 let lastResult; // 用来缓存上一次的结果 let calledOnce: boolean = false; // 是否调用过,刚开始的时候是false // 判断两次调用的时候的参数是否相等 // 这里的 `isEqual` 是一个抽象函数,用来判断两个值是否相等 const isNewArgEqualToLast = (newArg, index) => isEqual(newArg, lastArgs[index]); // 如果上一次的参数和这一次一样,直接返回上一次的结果 const result = function (...newArgs) { if ( calledOnce && newArgs.length === lastArgs.length && newArgs.every(isNewArgEqualToLast) ) { // 如果和上次的参数一致, 直接返回缓存的值 return lastResult; } // 如果和上一次的参数不一致,我们需要再次调用原来的函数 calledOnce = true; // 标记为调用过 lastArgs = newArgs; // 重新缓存参数 lastResult = resultFn.apply(this, newArgs); //重新缓存返回值 return lastResult; } // 返回闭包函数 return result; }
参考资料:
- 张容铭著 javascript设计模式 108-182页
- JavaScript权威指南
- https://github.com/alexreardon/memoize-one/blob/master/src/index.js
- https://zhuanlan.zhihu.com/p/37913276
- 点赞
- 收藏
- 分享
- 文章举报
- 设计模式笔记 13. TemplateMethod 模板方法模式(行为型模式)
- 设计模式 -- 行为型模式
- java设计模式(行为型)之职责链模式
- java设计模式(行为型)之模板方法模式
- 【设计模式】—-(16)观察者模式(行为型)
- [设计模式笔记]三. 行为型模式--18. Iterator模式(迭代器)对象行为型模式(一)
- Iterator迭代器设计模式学习(对象行为型)
- 设计模式——行为型模式(二)
- 设计模式笔记 17. Iterator 迭代器模式(行为型模式)
- 设计模式-行为型
- [设计模式-行为型]观察者模式(Observer)
- Java设计模式(15)行为型:观察者模式
- 设计模式实战13--行为型--策略模式
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
- 设计模式:行为型模式(2)
- 常用设计模式——行为型
- GoF23种设计模式之行为型模式之策略模式
- C#设计模式之十三模板方法模式(Template Method Pattern)【行为型】
- 设计模式18:Observer 观察者模式(行为型模式)
- 设计模式--命令模式Command(对象行为型)