JS设计模式(3)--- 复习
目录
[TOC]
桥接模式
侨接模式:将抽象部分与他的实现部分分离,使他们都可以独立的变化
使用场景,一个类存在两个或多个独立变化的维度,且这两个维度都需要扩展
优点 把抽象与实现隔离开,有助于独立管理各组成部分
缺点 每使用一个桥接元素都要增加一次函数调用,这样对应用程序的性能有一些负面的话影响提高了系统的复杂程度
function Aodi1(engine) {
this.engine = engine
}
Aodi1.prototype.platform = function () {
console.log('Aodi1 平台');
}
Aodi1.prototype.loadEngine = function () {
this.engine.run()
}
function v6(params) {
this.run = function () {
console.log('v6发动机');
}
}
function v8(params) {
this.run = function () {
console.log('v8发动机');
}
}
let car1 = new Aodi1(new v6())
let car2 = new Aodi1(new v8())
car1.loadEngine()
car2.loadEngine()
组合模式
组合模式在对象间形成树行结构
组合模式中基本对象和组合对象一致对待
无需关心对象多少层,调用时只需要在根部进行调用
他在我们树形结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部解耦
const Folder = function (falder) {
this.falder = falder
this.list = []//保存子文件夹或者文件
}
Folder.prototype.add = function (res) {
this.list.push(res)
}
Folder.prototype.scan = function () {
console.log('扫描文件夹', this.falder);
for (let i = 0; i < this.list.length; i++) {
this.list[i].scan()
}
}
const File = function (file) {
this.file = file
}
File.prototype.scan = function () {
console.log('开始扫描文件', this.file);
}
//根
let rootFolder = new Folder('root')
//子文件件
let htmlFolder = new Folder('html')
let cssFolder = new Folder('css')
let jsFolder = new Folder('js')
rootFolder.add(htmlFolder)
rootFolder.add(cssFolder)
rootFolder.add(jsFolder)
//文件
let html4 = new File('html4')
let html5 = new File('html5')
let css2 = new File('css2')
let css3 = new File('css3')
let es5 = new File('es5')
let es6 = new File('es6')
htmlFolder.add(html4)
htmlFolder.add(html5)
cssFolder.add(css2)
cssFolder.add(css3)
jsFolder.add(es5)
jsFolder.add(es6)
console.log(rootFolder);
rootFolder.scan()
命令模式
有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么,需要一种松耦合的方式来设计程序,使得发送者和接收者能够消除彼此之间的耦合关系 ·
命令模式由三种角色构成
- 发布者:发出命令,调用命令对象,不知道如何执行与谁执行
- 接收者:提供对应接口请求处理,不知道谁发起请求
- 命令对象:接收命令,调用接收者对应借口处理发布者的请求
class MacroCommand {
constructor() {
this.list = []//子命令对象
}
add(command) {
this.list.push(command)
}
execute() {
for (const item of this.list) {
item.execute()
}
}
}
const Tabs = {
execute() {
console.log("选项卡执行");
}
}
const Swiper = {
execute() {
console.log("轮播执行");
}
}
let macroCommand = new MacroCommand
macroCommand.add(Swiper)
macroCommand.add(Tabs)
macroCommand.execute()
迭代器模式
迭代器模式是提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示,迭代器模式可以把迭代的过程从业务逻辑中分析出来,在使用迭代器模式后,即使不关心对象的内部构造,也可以顺序访问其中的每个元素
- 为遍历不同的数据结构的集合提供统一接口
- 能遍历访问集合中的项,不关心项的数据结构
let kerwinEach = function (arr, callback) {
for (let i = 0; i < arr.length; i++) {
callback(i, arr[i])
}
}
kerwinEach([1, 2, 3], function (index, item) {
console.log(index, item);
})
es6 iterator
Array map set string arguments nodelist
for of 会调用 [Symbol.iterator]
let kerwinEach = function (arr, callback) {
for (let i = 0; i < arr.length; i++) {
callback(i, arr[i])
}
}
kerwinEach([1, 2, 3], function (index, item) {
console.log(index, item);
})
let list = [4, 5, 6]
let it = list[Symbol.iterator]()
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
let obj = {
0: 'zs',
1: 'ls',
2: 'ww',
length: 3,
[Symbol.iterator]: Array.prototype[Symbol.iterator]
}
for (const iterator of obj) {
console.log(iterator);
}
职责链模式
使多个对象可以处理请求,从而避免了请求的发送者,与多个接收者直接的耦合关系,将这些接收者链接成一条链,顺着这条链传递该请求,直到找到能处理该请求的对象
btn.onclick = function () {
checks.check()
// if (input.value.length == 0) {
// console.log('这里不能为空');
// } else {
// if (Number.isNaN(+input.value)) {
// console.log('必须是数字');
// } else {
// if (input.value.length < 6) {
// console.log('必须要大于6个数字');
// }
// }
// }
}
function checkEmty(params) {
if (input.value.length == 0) {
console.log('这里不能为空');
return
}
return 'next'
}
function checkNumber(params) {
if (Number.isNaN(+input.value)) {
console.log('必须是数字');
return
}
return 'next'
}
function checkLength(params) {
if (input.value.length < 6) {
console.log('必须要大于6个数字');
return
}
return 'next'
}
class Chain {
constructor(fn) {
this.checkRule = fn
this.nexRule = null
}
addRule(nexRule) {
this.nexRule = nexRule
}
check() {
this.checkRule() === 'next' ? this.nexRule.check() : null
}
}
let checks = new Chain(checkEmty)
const checkNumberChain = new Chain(checkNumber)
const checkLengthChain = new Chain(checkLength)
checks.addRule(checkNumberChain)
checks.addRule(checkLengthChain)
checkLengthChain.addRule({
check: () => {
console.log('ok');
return 'end'
}
})
优点
- 符合单一单职责,使每个方法中只有一个职责
- 符合开放封闭原则,在需求增加时,可以很方便的扩冲新的职责
- 使用时不需要知道谁才是真正的处理方法,减少大量的if else语法
缺点
- 团队成员需要对职责链存在共识,否则当看到一个方法莫名其妙的返回一个next时一定会奇怪
- 出现错误时不好排查,因为不知道在那个责任中出的错,需要从链头开始往后找