Skip to content

设计模式

学习设计模式有助于写出优质代码。

工厂模式

工厂模式属于创建型模式,提供一种创建对象的最佳方式。

简单工厂

简单工厂中,在不暴露创建对象的具体细节,通过接口来创建对象。就像工厂一样,不需要了解具体生成细节,要什么产品,就请求什么产品。

如下代码,要什么动物调用animal.getAnimal(type)即可。Animal就像一个大工厂一样,不关心对象内部具体如何实现。

js
class Pig {
  constructor() {}
  getType() {
    console.log('you get a pig')
  }
}
class Cat {
  constructor() {}
  getType() {
    console.log('you get a cat')
  }
}
class Animal {
  //动物工厂
  constructor() {}
  getAnimal(type) {
    if (type === 'cat') return new Cat()
    else if (type === 'pig') return Pig()
  }
}
const animal = new Animal()
const cat = animal.getAnimal('cat')
cat.getType() //you get a cat

抽象工厂

抽象工厂就像是再对Animal再进行了一次工厂模式。

如下先获取动植物类别,再具体化对象。

js
class Orchid {
  constructor() {}
  getType() {
    console.log('you get an orchid')
  }
}
class Cat {
  constructor() {}
  getType() {
    console.log('you get a cat')
  }
}
class Plant {
  constructor() {}
  getPlant(type) {
    if (type === 'orchid') return new Orchid()
  }
}
class Animal {
  constructor() {}
  getAnimal(type) {
    if (type === 'cat') return new Cat()
  }
}

class Biology {
  //更高一层的工厂
  static getBiology(type) {
    if (type === 'animal') return new Animal()
    else return new Plant()
  }
}
const animal = Biology.getBiology('animal')
const cat = animal.getAnimal('cat')
cat.getType() //you get a cat
const plant = Biology.getBiology('plant')
const orchid = plant.getPlant('orchid')
orchid.getType() //you get an orchid

application scenarios

提示

未完待续

单例模式

单例模式属于创建型模式,这个类提供一种访问其唯一对象的方式。

单例模式实现有懒汉式饿汉式,区别为是否在类方法外创建对象。饿汉式式声明并创建对象,懒汉式在调用getInstance()时才会创建对象。如:Window对象等。

懒汉式

js
class Single {
  static #instace = null
  static getInstance() {
    if (!this.#instace) {
      this.#instace = new Single()
    }
    return this.#instace
  }
  get() {
    return 'single'
  }
}
const obj1 = Single.getInstance()
const obj2 = Single.getInstance()
console.log(obj1 === obj2) //true

饿汉式

js
class Single {
  static #instace = new Single()
  static getInstance() {
    return this.#instace
  }
  get() {
    return 'single'
  }
}
const obj1 = Single.getInstance()
const obj2 = Single.getInstance()
console.log(obj1 === obj2) //true

application scenarios

提示

未完待续

观察者模式

观察者模式又叫发布-订阅模式,属于行为型模式

观察者模式适用于对象间存在一对多关系的情况。一个对象变化,通知其余依赖这个对象的对象。如:MVVM的实现,单向绑定,DOM 事件等。

js
class Observer {
  constructor(name) {
    this.name = name
  }
  update() {
    this.aboutMe()
  }
  aboutMe() {
    console.log(`I am ${this.name}`)
  }
}
class Publisher {
  constructor() {
    this.observers = []
  }
  add(observer) {
    this.observers.push(observer)
    return this //便于链式调用
  }
  notify() {
    this.observers.forEach(observer => {
      observer.update()
    })
  }
  IntroduceObserver() {
    console.log('Please introduce yourself')
    this.notify()
  }
}
const zs = new Observer('zs')
const ls = new Observer('ls')
const lx = new Publisher()
lx.add(zs).add(ls)
lx.IntroduceObserver()
//Please introduce yourself
//I am zs
//I am ls

application scenarios

提示

未完待续

策略模式

策略模式属于行为型模式,策略模式中一个类的行为可以在运行时候进行更改。

常用于:if else分支修改,重构代码等。

js
const _price = (type, price) => {
  if (type === 'A') {
    return price * 0.9
  } else if (type === 'B') {
    return price * 0.8
  } else return price * 1
}

在进行添加其他类型型式会不可避免去修改原函数,而且通常大量得if else会不好修改和难于修改。

使用策略模式修改如下:只需添加不同打折的对象即可。

js
class ActivityA {
  getMoney(price) {
    return price * 0.9
  }
}
class ActivityB {
  getMoney(price) {
    return price * 0.8
  }
}
class Context {
  #activityType
  constructor(type) {
    this.#activityType = type
  }
  getMoneyByType(money) {
    console.log(`this price is ${this.#activityType.getMoney(money)}`)
  }
}
let context = new Context(new ActivityA())
context.getMoneyByType(100) //this price is 90
context = new Context(new ActivityB())
context.getMoneyByType(100) //this price is 80

application scenarios

提示

未完待续

装饰器模式

装饰器模式属于结构型模式。

装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。

高阶函数就是一个装饰器模式例子。

js
class Div {
  about() {
    console.log('this is a div')
  }
}
class BorderDecorator {
  constructor(div) {
    this.div = div
  }
  about() {
    this.div.about()
    this.setBorder()
  }
  setBorder() {
    console.log('Border')
  }
}
const borderDiv = new BorderDecorator(new Div())
borderDiv.about()
//this is a div
//Border

application scenarios

提示

未完待续

适配器模式

适配器模式解决两个接口不兼容的问题。如:音频播放器。

js
class Mp4 {
  //mp4接口
  play() {
    console.log('it is mp4')
  }
}
class Video {
  //video接口
  play() {
    console.log('is is video')
  }
}
class Media {
  constructor(type) {
    if (type === 'mp4') this.type = new Mp4()
    else if (type === 'video') this.type = new Video()
  }
  play() {
    this.type.play()
  }
}
class AudioPlayer {
  play(type) {
    if (type === 'mp3') {
      //原生接口
      console.log('it is mp3')
    } else if (type === 'mp4' || type === 'video') {
      new Media(type).play()
    }
  }
}
const audio = new AudioPlayer()
audio.play('mp4')
//it is mp4

application scenarios

提示

未完待续

代理模式

代理模式属于结构型模式。

在代理模式中,一个类代表另一个类的功能。

js
class Date {
  constructor(url) {
    this.url = url
  }
  getDate() {
    console.log(`这是从${this.url}请求的数据`)
  }
}
class ProxyDate {
  #Date
  constructor(url) {
    this.url = url
  }
  getDate() {
    if (!this.#Date) {
      this.#Date = new Date(this.url) //代理请求
    }
    this.#Date.getDate()
  }
}
const proxyD = new ProxyDate('www.xxxx.com/getDate')
proxyD.getDate() //这是从www.xxxx.com/getDate请求的数据
proxyD.getDate() //不会再次真正请求

application scenarios

提示

未完待续

Released under the MIT License.