JavaScript中常见的设计模式

设计原则

单一职责原则(SRP)

一个对象或方法只做一件事情。如果一个方法承担了过多的职责,那么在需求的变迁过程中,需要改写这个方法的可能性就越大。应当把方法或对象划分成较小的粒度

最少知识原则(LKP)

一个软件实体应当尽可能少地与其他实体发生相互作用。应当尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那两个对象就不要发生直接的相互联系,可以转交给第三方进行处理

开放-封闭原则(OCP)

软件实体(类、模块、函数)等应该是可以拓展的,但是不可修改

当需要改变一个程序的功能或者给这个程序增加新功能的时候,可以使用增加代码的方式,尽量避免改动程序的源代码,防止影响源系统的稳定

一、单例模式

1、定义

保证一个类仅有一个实例,并提供一个访问他的全局访问点

2、核心

确保只有一个实例,并提供全局访问

3、实现

多次调用也仅设置一次,可以使用闭包的方式缓存一个内部变量来实现这个单例

4、目的

为了防止频繁的创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一实例对象。

单例模式的类型

懒汉模式:在真正需要使用对象时才去创建该单例

饿汉模式:在类加载是已经创建好该单例对象,等待被程序使用

懒汉模式创建单例对象

懒汉式创建对象的方式是在程序使用对象前,先判断该对象是否已经实例化(判空),若已经实例化直接返回该类对象。否则则先执行实例化操作。

var Singleton = (function(){
    var instantiated;//比较懒,在加载时,不创建实例,因此类加载速度快,但运行时获取对象的速度慢
    function init(){
        return {
            publicMethod:function(){
                console.log('helloWorld')
            },
            publicProperty:3
        }
    }
    return {
        // 使用闭包保存变量
        getInstance:function (){
            if(!instantiated){
                instantiated=init() //第一次调用时执行
            }
            return instantiated//返回实例对象
        }
    }
})()//使用立即执行函数在类加载时执行
//可在其他类调用公有的方法或属性来获取实例
Singleton.getInstance().publicMethod()
// 再次执行的时候也是执行的第一次init()方法
Singleton.getInstance().publicMethod()
Singleton.getInstance().publicProperty=4
console.log(Singleton.getInstance().publicProperty)

饿汉模式

饿汉式在类加载时已经创建好该对象,在程序调用时直接返回该单例对象即可,即我们在编码时就已经指明了要马上创建这个对象,不需要等到被调用时再去创建。

var Singleton1 = (function (){
    //比较饥饿,在类加载时就完成了初始化,所以类加载比较慢,但获取对象的速度快
    var instantiated = init();
    function init(){
        return {
            publicMethod:function (){
                console.log('helloWorld')
            },
            publicProperty:3
        }
    }
    return {
        getInstance:function (){
            return instantiated
        }
    }
})()

二、发布订阅

定义

发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于他的对象都将得到状态改变的通知

实现思路

创建一个对象

在该对象上创建一个缓存列表(即调度中心)

on方法用来把函数fn都加到缓存队列中(订阅者注册事件到调度中心)

emit方法取到arguments里第一个当做event,根据event值去执行对应缓存列表中的函数(发布者发布事件到调度中心,调度中心处理订阅者订阅时的方法)

off方法可以根据event值取消订阅

once方法值监听依次,调用完毕后删除缓存函数

demo实现on和emit方法

//调度中心
let eventEmitter = {}
//缓存列表,存放event及fn
eventEmitter.list={}
//订阅
eventEmitter.on = function (event,fn){
    let _this = this;
    //如果对象中没有对应的event值,也就是说明没有订阅过,就给event创建个缓存列表
    //如果对象中有相应的event值,把fn添加到对应的event的缓存列表里
    (_this.list[event] || (_this.list[event]=[])).push(fn)
    return _this
}
eventEmitter.emit = function (){
    let _this = this;
    //第一个参数是对应的event值,直接用数组的shift方法取出
    let event = [].shift.call(arguments),
        fns = [...this.list[event]]
    // 该事件注册的所有方法 fns
    console.log(event,'事件名')
    if(!fns || fns.length === 0){
        return false
    }
    //遍历event值对应的缓存列表,依次执行fn
    fns.forEach(fn=>{
        fn.apply(_this,arguments)
    })
    return _this
}
    function user1(content){
        console.log('用户1订阅了:',content)
    }
    function user2(content){
        console.log('用户2订阅了',content)
    }
    //订阅
eventEmitter.on('article',user1)
eventEmitter.on('article',user2)

// 发布
eventEmitter.emit('article','javascript 发布-订阅模式')

观察者模式和发布订阅模式的区别

观察者模式:观察者直接订阅主题,而当主题被激活的时候,会触发观察者里的事件

发布订阅模式:订阅者吧自己想订阅的事件注册到调度中心,发布者发布该事件到调度中心,也就是该事件触发时,由调度中心统一调度,订阅者注册到调度中心的处理代码

差异

在观察者模式中,观察者是知道subject的,subject一直保持对观察者进行记录。然而在发布订阅者模式中发布者和订阅者不知道对方的存在。

他们只有通过消息代理进行通信

在发布订阅模式中,组件是松耦合的,正好和观察者模式相反

观察者模式大多数时候是同步的,比如当事件触发,Subject 就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)。

观察者模式需要在单个应用程序地址空间中实现,而发布-订阅更像交叉应用模式。

三、装饰器模式

定义:装饰器模式能够在不改变对象自身的基础上,动态的给某个对象添加额外的职责,不会影响原有接口的功能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值