JavaScript设计模式-004

69 阅读1分钟

桥接模式

将抽象部分与实现部分分离,使它们都可以独立的变化

使用场景:一个类存在两个或多个独立变化的维度,且这两个维度都需要进行扩展

function Audi1(engine) {
  this.engine = engine
}

Audi1.prototype.platform = function(){
  console.log('audi1 平台');
}

Audi1.prototype.loadengine = function() {
  //
  this.engine.run()
}

function Audi2(engine) {
  this.engine = engine
}

Audi2.prototype.platform = function(){
  console.log('audi2 平台');
}

Audi2.prototype.loadengine = function() {
  //
  this.engine.run()
}

function V6() {
  this.run = function () {
    console.log('V6');
  }
}

function V8() {
  this.run = function () {
    console.log('V8');
  }
}

let audi = new Audi1(new V6())
audi.loadengine()

let audi2 = new Audi2(new V8())
audi2.loadengine()

缺点:提高了代码的复杂度

组合模式

组合模式在对象间形成树形结构

组合模式中基本对象和组合对象被一致对待

无需关心对象有多少层,调用时只需在根本进行调用

const Folder = function (folder) {
  this.folder = folder
  this.list = [] //保存 子文件
}

Folder.prototype.add = function (res) {
  this.list.push(res)
}

Folder.prototype.scan = function() {
  console.log('扫描文件夹', this.folder);
  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 html1 = new File('html1')
let html2 = new File('html2')
let css1 = new File('css1')
let css2 = new File('css2')
let js = new File('js')
let js3 = new File('js3')

htmlFolder.add(html1)
htmlFolder.add(html2)
cssFolder.add(css1)
cssFolder.add(css2)
jsFolder.add(js)
jsFolder.add(js3)

rootFolder.scan()

命令模式

由三部分构成

发布者Invoker 发出命令,调用命令对象,不知道如何执行与谁执行

接收者 receiver 提供接口处理请求 不知道谁发起请求

命令对象 command 接收命令,调用接收者对应接口处理发布者的请求

class Receiver {
  //接受类
  execute() {
    console.log('接收');
  }
}

class Command {
  constructor(reveiver) {
    this.reveiver = reveiver
  }
  //命令类
  execute() {
    console.log('命令');
    this.reveiver.execute()
  }
}

class Invoker {
  constructor(command) {
    this.command = command
  }
  //发布类
  order() {
    console.log('发布');
    this.command.execute()
  }
}

const order = new Command(new Receiver())

const client = new Invoker(order)

client.order()

模板方法模式

由两部分组成,抽象父类,具体的实现子类,通常在抽象父类中封装子类的算法,包括实现一些公共方法以及子类的所有方法执行顺序,子类继承了这个抽象类,也继承了所有算法。

const Container = function (params = {}) {
  const F = function () {
  
  }
  
  F.prototype.init = function () {
    this.getData()
    this.render()
  }
  
  F.prototype.getData = params.getData || function () {
    throw new Error('必须传入getData')
  }
  
  F.prototype.render = function () {
    console.log('render');
  }

  return F
}

let myClass = Container({
  getData() {
    console.log('获取数据');
  }
})

new myClass().init()

迭代器模式

迭代器模式指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器可以把迭代过程从业务逻辑中分离开来,即使不关心对象内部构造,也可以按照顺序访问内部每个元素。

let iterator = function (arr, callback) {
  for (let index = 0; index < arr.length; index++) {
    callback(index, arr[index])
    
  }
}

iterator([66, 77, 88], function(key, value) {
  console.log(key, value);
})

责任链模式

使多个对象都有机会处理请求,从而避免了请求的发送者与多个接收者直接的耦合关系,将这些接收者形成一条链,顺着这条链传递该请求,直到能处理该请求的对象。

let arr = [99, 88]

let num = '7'

function checkEmpty() {
  if (arr.length !== 0) {
    return
  }
  return 'next'
}

function checkSeven() {
  if (num !== '7') {
    return
  }
  return 'next'
}
class Chain {
  constructor(fn) {
    this.checkRole = fn
    this.nextRole = null
  }

  addRole(nextRole) {
    this.nextRole = new Chain(nextRole)
    return this.nextRole
  }

  check() {
    this.checkRole() === 'next' ? this.nextRole.check() : null
  }
}

const checks = new Chain(checkEmpty)

checks.addRole(checkEmpty).addRole(checkSeven).addRole(() => {
  'end'
})