尼采般地抒情

尼采般地抒情

尼采般地抒情

音乐盒

站点信息

文章总数目: 316
已运行时间: 1570

一、单例模式

类只有一个实例,像BOM这个全局对象就是单例模式,还有单独创建一个对象字面量,也是单例模式,下面讲述单例模式的实现:

class Aoteman {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  // 实现单例模式
  static getInstance(name, age) {
    if (!this.instance) {
      this.instance = new Aoteman(name, age)
    }
    return this.instance
  }

Ability = data => {
console.log(this.name + ‘ can ‘ + data)
}
}

const dijia = new Aoteman(‘dijia’, ‘2022’)
console.log(dijia.name)
dijia.Ability(‘X-ray’)

let tailuo = Aoteman.getInstance(‘tailuo’, ‘1990’)
console.log(tailuo.name)
tailuo.Ability(‘Y-ray’)
let aidi = Aoteman.getInstance(‘aidi’, ‘1990’)
console.log(aidi.name)
tailuo.Ability(‘Z-ray’)
console.log(‘———————‘)
console.log(dijia === tailuo)
console.log(tailuo === aidi)

上面的方式实现,只能调用getInstance方法才能创建单例,如果用户再次使用new来创建实例,还是不可行,所以还需要对上述予以工厂模式封装:

const singleFactory = (...rest) => {
  return Aoteman.getInstance(...rest)
}

使用场景:发布订阅场景,我们需要在一个地方进行订阅,在另一个地方进行发布,这样就需要保证在不同文件中访问到的是同一个实例。

class PubSub {
  constructor() {
    this.listeners = {}
  }
  publish(event, data) {
    if (!this.listeners[event]) {
      return;
    }
    this.listeners[event].forEach(listener => {
      listener(data);
    })
  }
  subscribe(event, callback) {
    if (!this.listeners[event]) {
      this.listeners[event] = []
    }
    this.listeners[event].push(callback);
  }
}
export default new PubSub

二、工厂模式

  • 优点:一个工厂创建同一类对象,更好的归类创建
  • 抽象工厂模式的缺点就是,如果需要增加新的产品,比如要生产可乐周边玩偶,这就需要对原有的抽象工厂接口进行改造,不符合开闭原则。
function CreateElement(type) {
  switch (type) {
    case 'Input':
      return new Input()
      break;
    case 'Div':
      return new Div()
      break;
    default:
      throw new Error('无当前产品')
  }
}

function Input() {
return document.createElement(‘input’)
}

function Div() {
return document.createElement(‘div’)
}

//test
const input = new CreateElement(‘Input’);
const div = new CreateElement(‘DIV’);
console.log(input) // input
console.log(div) // div

class User {
  constructor(name) {
    this.name = name
  }
  SetRoleType(type) {
    switch (type) {
      case 'Admin':
        return new UserAdmin()
        break
      case 'Member':
        return new UserMember()
        break
      default:
        throw new Error('Set Error!')
    }
  }
  GetName = () => {
    console.log('this name is: ' + this.name)
  }
}
class UserAdmin extends User {
  constructor(name) {
    super(name)
    this.name = name
  }
  RoleInfo = () => {
    console.log('Type is Admin ')
  }
}

const zhangsan = new User('zhangsan')
zhangsan.GetName()
zhangsan.SetRoleType('Admin').RoleInfo()

建造者模式

/**
 * 建造者模式
 */

/* 建造者 */
function ComputerBuilder(brand) {
this.brand = brand
}

ComputerBuilder.prototype.buildCPU = function (type) {
switch (type) {
case ‘inter’:
this.cpu = ‘inter处理器’
break;
case ‘AMD’:
this.cpu = ‘AMD处理器’
break;
}

return this
}

ComputerBuilder.prototype.buildMemory = function (mSize) {
thgis.mSize = ‘内存’ + mSize + ‘G’
return this
}

ComputerBuilder.prototype.buildDisk = function (dSize) {
this.dSize = ‘硬盘’ + dSize + ‘G’
return this
}

/* 厂家,负责组装 */
function computerDirector(brand, type, mSize, dSize) {
const _computer = new ComputerBuilder(brand)
_computer.buildCPU(type)
.buildMemory(mSize)
.buildDisk(dSize)

return _computer
}

//test
const com = computerDirector(‘联想’, ‘inter’, 16, 500);
console.log(com); // ComputerBuilder {brand: "联想", cpu: "inter 处理器", mSize: "内存16G", dSize: "硬盘500G"}

代理模式

/**
 * 代理模式
 */

/* 目标 */
function sendMsg(msg) {
console.log(msg)
}

/* 代理 */
function ProxyMsg(msg) {
if (!msg) {
console.log(‘msg is empty’)
return
}

msg = ‘我要发送的数据是’ + msg
sendMsg(msg)
}

// test
ProxyMsg(‘您好!’)

享元模式

/**
 * 享元模式
 */

/* 享元对象 */
function Shape(shape) {
this.shape = shape
}

shape.prototype.draw = function () {
console.log(画了一个${this.shape})
}

/* 享元工厂 */
const ShapeFactory = (function () {
const dataMap = {}
return {
getShapeContext(shape) {
if (dataMap[shape]) return dataMap[shape]
else {
const instance = new Shape(shape)
dataMap[shape] = instance
return instance
}
}
}
})()

// test
const rect = ShapeFactory.getShapeContext(‘rect’);
const circle = ShapeFactory.getShapeContext(‘circle’);

rect.draw(); // 画了一个 rect
circle.draw(); // 画了一个 circle

适配器模式

/**
 * 适配器模式
 */

const baiduMap = {
show: function () {
console.log(‘开始渲染百度地图’)
}
}

const AMap = {
show: function () {
console.log(‘开始渲染高德地图’)
}
}

/* 适配器 */
const baiduAdapter = {
render: function () {
return baiduMap.show()
}
}

function renderMap(map) {
if (typeof map.render === ‘function’) {
map.render()
}
}

// test
renderMap(AMap); // 开始渲染高德地图
renderMap(baiduAdapter); // 开始渲染百度地图

装饰器模式

/**
 * 装饰器模式
 */

const btn = document.querySelector(‘#btn’)

// 原绑定事件
btn.onclick = function () {
console.log(‘按钮被点击了’)
}

// 新增统计
function ajaxToServer() {
console.log(‘数据统计’)
}

// 装饰器函数
function decorator(target, eventName, cb) {
const originFn = target[‘on’ + eventName]
originFn && originFn()
cb && cb ()
}

// test
decorator(btn, ‘click’, ajaxToServer)

外观模式

/**
 * 外观模式 
 */

// 事件绑定
function addEvent(element, type, fn) {
if (element.addEventListener) {
element.addEventListener(type, fn, false)
} else if (element.attachEvent) {
element.attachEvent(‘on’ + type, fn)
} else {
element[‘on’ + type] = fn
}
}

// 阻止事件冒泡
function cancelBubble(event) {
if (event.stopPropagation) {
event.stopPropagation()
} else {
event.cancelBubble = true
}
}

// axios 中 getDefaultAdapter
function getDefaultAdapter() {
var baiduAdapter
if (typeof process !== ‘undefined’ && Object.prototype.toString.call(process) === ‘[object process]’) {
adapter = ‘a’
} else if (typeof XMLHttpRequest !== ‘undefined’) {
adapter =’b’
}

return adapter
}


组合模式

/**
 * 组合模式
 */

// 创建部门
function createApartment(name) {
return {
name,
_children: [],
add(target) {
this._children.push(target)
return this
},
show(cb) {
this._children.forEach(function(child) {
child.show(cb)
})
}
}
}

// 创建员工
function createEmp(num, name) {
return {
num,
name,
show(cb) {
cb(this)
}
}
}

// 创建部门
const techApartment = createApartment(‘技术部’)

// 创建子部门
const proApartment = createApartment(‘产品组’),
devApartment = createApartment(‘开发组’)

techApartment.add(proApartment).add(devApartment)

proApartment.add(createEmp(100, ‘张三’))
.add(createEmp(101, ‘李四’))

techApartment.add(createEmp(201, ‘小刘’))
.add(createEmp(202, ‘小王’))
.add(createEmp(203, ‘小陈’))
.add(createEmp(204, ‘小亮’))

// 遍历
techApartment.show(function (item) {
console.log(工号:${item.num},姓名:${item.name})
})


桥接模式

/**
 * 桥接模式
 */

// 桥接方法
function addEvent(ele, eventName, fn) {
document.querySelector(ele).addEventListener(eventName, fn, false)
}

// 具体业务
addEvent(‘#btn’, ‘click’, function () {
console.log(‘hello world’)
})

发布-订阅模式

// 事件监听器
const Emitter = (function () {
  const _events = {}
  return {
    // 事件绑定
    on(type, cb) {
      if (!_events[type]) {
        _events[type] = []
      }
      if (typeof cb === 'function') {
        _events[type].push(cb)
      } else {
        throw new Error('参数类型必须为函数')
      }
    },
    // 事件解绑
    off(type, cb) {
      if (!_events[type] || !_events[type].includes(cb)) return 
      // 移除事件监听
      _events[type].map((fn, index) => {
        if (fn == cb) {
          _events[type].splice(index, 1)
        }
      })
    },
    emit(type, ...args) {
      if (!_events[type]) return
      _events[type].forEach(cb => cb(...args))
    }
  }
})()

// 事件订阅
Emitter.on(‘change’, data => console.log(我是第一条信息:${data}))
Emitter.on(‘change’, data => console.log(我是第二条信息:${data}))

// 事件发布
Emitter.emit(‘change’, ‘参数’)

发布-订阅模式和观察者模式相近,具体区别有:

策略模式

/**
 * 策略模式
 */

// 校验规则
const strategyMap = {
// 校验手机号
isMobile(mobile) {
return /^1\d{10}$/.test(mobile)
},
// 校验是否必填
isRequired(str) {
return str.replace(/(^\s*)|(\s*$)/g, ‘’) !== ‘’
}
}

// 校验方法
function validate(formData) {
let valid

for (let key in formData) {
const val = formData[key]?.value
const rules = formData[key]?.rules

for (let i = 0; i < rules.length; i++) {
  const result = strategyMap[rules[i]['rule'].call(null,val)]
  if (!result) {
    valid = {
      errField: key,
      errValue: value,
      errMsg: rules[i]['message']
    }
    break
  }
}

if (valid) return valid

}

return valid
}

// form 表单校验
const formData = {
mobile: {
value: ‘1380000000’,
rules: [
{ rule: ‘isRequired’, message: ‘手机号码不能为空’ },
{ rule: ‘isMobile’, message: ‘手机号码格式不正确’ }
]
}
}

// 获取校验结果
const valid = validate(formData)
if (!valid) {
console.log(‘校验通过’)
} else {
console.log(valid)
}

状态模式

/**
 * 状态模式
 */

// 正常状态
function NormalState() {
this.handleChange = function (context) {
console.log(‘正常状态’)
context.state = new ColorfulState()
}
}

// 彩灯状态
function ColorfulState() {
this.handleChange = function (context) {
console.log(‘彩灯状态’)
context.state = new CloseState()
}
}

// 关闭状态
function CloseState() {
this.handleChange = function (context) {
console.log(‘关闭状态’)
context.state = new NormalState()
}
}

// 灯
function Light(state) {
this.state = state
this.switch = function () {
this.state.handleChange(this)
}
}

// 设置灯光初始为关闭
const light = new Light(new CloseState())

// 关闭状态–>正常状态–>彩灯状态–>关闭状态…
setInterval(() => {
light.switch()
}, 1000)

命令模式

/**
 * 命令模式
 */

const Manager = (function () {
// 命令
const commander = {
open: function () {
console.log(‘打开电视’)
},
close: function () {
console.log(‘关闭电视’)
},
change: function (channel) {
console.log(‘更换频道’ + channel)
}
}

return {
// 执行命令
exec: function (cmd) {
const args = [].splice.call(arguments, 1)
commander[cmd] && commander[cmd][args]
}
}
})

// test
Manager.exec(‘open’) // 打开电视
Manager.exec(‘change’, 10) // 更换频道 10
Manager.exec(‘close’) // 关闭电视

参考

评论区