2022-05-23 设计模式

设计模式 5 大原则

1,单一职责原则
一个类只封装一定的功能
过于复杂的代码块想办法拆分成单独的方法

2,开闭原则
对修改关闭,对扩展开放
增加或者变更需求时,不应该修改核心代码,应该再之前的基础上新增功能

3,里氏替换原则
父类能用的地方,子类都能用,即可以用任何子类替换父类

4,接口隔离原则
接口之间功能不要重复
接口更纯粹干净

5,依赖倒置原则
使用方应该依赖抽象,比如接口,抽象类,配置等,而不是其实现,因为实现会频繁变更

设计模式分类

1,创建型

1,单例模式
一个类只有一个全局实例,并提供一个获取它的全局入口。

class LoginForm {
  constructor() {
  }
}
//用闭包存一个永久的单例
LoginForm.getInstance = (function () {
  let instance = null
  return = function () {
    if (!instence) {
      instance = new LoginForm()
    }
    return instance
  }
})()

2,工厂模式
如果不想让某个子系统与较大的哪个对象之间形成强耦合。而是想在运行时可以从许多系统进行挑选或者切换的话。工厂模式可以进行解耦。

class product1 {
  run () { }
}

class product2 {
  run () { }
}

class Fatory {
}

Fatory.create(productName) {
  if (productName === '1') {
    return new product1()
  }
  else {
    return new product2()
  }
}

let p = Fatory.create('1')
p.run()

2,结构型

1,适配器模式
适配器用于解决两个接口不兼容的情况,通过适配器可以在不改变原有接口源码的情况下,让两个不兼容的接口通信

//客户端接收一个对象,必须有run方法
class client {
  constructor(app) {
    this.app = app
  }

  run () {
    this.app.run()
  }
}

//appForien没有run方法,无法与client兼容
class appForien {
  constructor(name) {
    this.name
  }
  business () {
    return this.name
  }
}

//创建Forien适配器
class forienAdapter {
  constructor(app) {
    this.app = app
  }

  run () {
    const result = this.app.business()
    return result
  }
}

//使用
const app = new appForien()
const fa=new forienAdapter(app)
const c = new client(fa)
c.run()

应用场景:vue中的computed就是适配器,将原先各种数据组装成客户端能用的新数据

2,装饰器模式
动态的给对象或者函数添加某些功能

class cellPhone {
  create () {
  }
}

class Decorator {
  constructor(cellPhone, funcBefore, funcAfter) {
    this.cellPhone = cellPhone
  }

  create () {
    funcBefore()
    this.cellPhone.create()
    funcAfter()
  }
}

//使用
const d = new Decorator(new cellPhone(), () => {
  //前置功能
}
  , () => {
    //后置功能
  })
d.create()

3,代理模式
客户端不直接与接口进行通信,而是加一个代理层进行通讯

class client {
  constructor() {
    this.msg = ''
  }
  getMsg () {
    return this.msg
  }

  setMsg (msg) {
    this.msg = msg
  }
}

class msgProxy {
  constructor(client, encodeMsg) {
    this.client = client
    this.encodeMsg = encodeMsg
  }
  getMsg () {
    return this.encodeMsg(this.client.getMsg())
  }

  setMsg (msg) {
    const msgStr = this.encodeMsg(msg)
    this.client.setMsg(msgStr)
  }
}

//使用
const c = new client()
const p = new msgProxy(c, (str) => {
  return str + '111'
})
p.setMsg('aaa')
console.log(p.getMsg())

4,组合模式

3,行为型

1,观察者模式
定义了一种一对多的模式。有多个观察者监听一个主题,只要主题发送通知,所有观察者都会进行响应。
这其中的关键是主题要收集到所有的观察者。然后有一个通知方法,循环遍历通知每一个观察者。对于观察者而言,他们有一个依赖的
主题,并且有一个同名的响应方法。

//一个主题,用于收集依赖,发布通知
class Subject {
  constructor() {
    this.state = 0
    this.observers = []
  }

  getState () {
    return this.state
  }

  setState (state) {
    this.state = state
    this.notifyAllObservers()
  }

  notifyAllObservers () {
    this.observers.forEach(ob => {
      ob.update()
    })
  }

  attach (observer) {
    this.observers.push(observer)
  }
}

//观察者,用于跟踪主题,响应通知
class Observer{
  constructor(name,subject){
    this.name = name
    this.subject = subject
    this.subject.attach(this)
  }

  update(){
    //do something
  }
}

2,迭代器模式
提供一种方法顺序执行一个聚合对象中各个元素,而又不暴露该对象得内部表示

class Iterator {
  constructor(container) {
    this.list = container.list
    this.index = 0
  }

  next () {
    if (this.hasNext()) {
      //do something
      return this.list[this.index++]
    }
    return null
  }

  hasNext () {
    return this.index >= this.list.length
  }
}

class Container{
  constructor(list){
    this.list = list
  }

  getIterator(){
    return new Iterator(this)
  }
}

//使用
const con = new container([1,2,3,4,5])
let iterator = con.getIterator()

while(iterator.hasNext()){
  iterator.next()
}

3,策略模式
将不同的可能用到的方法封装在一起,并且他们可以互相替换

//应用场景:表单验证
//策略对象
class strategies {
  static isRequire (value, errorMsg) {
    if (!value) {
      console.log(errorMsg)
    }
  }

  static minLength (value, errorMsg, length) {
    if (value.length < length) {
      console.log(errorMsg)
    }
  }
}

//验证类
class Validator {
  constructor(form) {
    this.form = form
  }
  valid (rules) {
    rules.forEach(rule => {
      rule.stratege(form[rule.name], rule.errorMsg,rule.args)
    });
  }
}

//使用,配置策略
const rules = [
  { name: id, stratege: strategies.isRequire, errorMsg: '必填' },
  { name: address, stratege: strategies.minLength, errorMsg: '过长', args: 10 },
]

const formValidator = new Validator({
  id:'123',
  address:'tom jack no 100'
}).valid(rules)

4,模板方法模式
将一个过程或者一个流程算法的公共部分提取出来,可变部分的逻辑给子类去实现和变动,整个大步骤不变

class flow{
  constructor(step1,step2){
    this.step1=step1
    this.step2=step2
  }

  run(){
    this.start()
    this.step1()
    this.step2()
    this.end()
  }

  start(){
    console.log('start')
  }

  end(){
    console.log('end')
  }
}

5,命令模式
将执行逻辑和执行对象之间解耦,使得执行逻辑可以更容易扩展

//接收器
class Receiver {
  run () {
    console.log('run start')
  }
}

//命令类型
class Command {
  constructor(Receiver) {
    this.Receiver = Receiver
  }

  execute () {
    this.Receiver.run()
  }
}

//命令触发器
class Invoker {
  constructor(Command) {
    this.Command = Command
  }

  invoke () {
    this.Command.execute()
  }
}

//使用,客户下订单发货
const base = new Receiver() //仓库
const order = new Command(base) //订单
const client = new Invoker(order) //客户
//客户下订单
client.invoke()


6,中介模式
将多个对象的直接交互,变成由一个中介对象来间接交互,可以将交互对象之间解耦

class A {
  constructor() {
    this.val = ''
  }
  setB (m, val) {
    m.setB(val)
  }
}

class B {
  constructor() {
    this.val = ''
  }
  setA (m, val) {
    m.setA(val)
  }
}

//中介者
class Mediator {
  constructor(a, b) {
    this.a = a
    this.b = b
  }
  setA (val) {
    A.val = val
  }
  setB (val) {
    A.val = val
  }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容