zoukankan      html  css  js  c++  java
  • JS实现单例模式的多种方案

    JS实现单例模式的多种方案

    今天在复习设计模式中的-创建型模式,发现JS实现单例模式的方案有很多种,稍加总结了一下,列出了如下的6种方式与大家分享

    大体上将内容分为了ES5(Function)与ES6(Class)实现两种部分

    单例模式的概念

    • 一个实例只生产一次
    • 保证一个类仅有一个实例,并提供一个访问它的全局访问点

    方式1

    利用instanceof判断是否使用new关键字调用函数进行对象的实例化

    function User() {
        if (!(this instanceof User)) {
            return
        }
        if (!User._instance) {
            this.name = '无名'
            User._instance = this
        }
        return User._instance
    }
    
    const u1 = new User()
    const u2 = new User()
    
    console.log(u1===u2);// true
    

    方式2

    在函数上直接添加方法属性调用生成实例

    function User(){
        this.name = '无名'
    }
    User.getInstance = function(){
        if(!User._instance){
            User._instance = new User()
        }
        return User._instance
    }
    
    const u1 = User.getInstance()
    const u2 = User.getInstance()
    
    console.log(u1===u2);
    

    方式3

    使用闭包,改进方式2

    function User() {
        this.name = '无名'
    }
    User.getInstance = (function () {
        var instance
        return function () {
            if (!instance) {
                instance = new User()
            }
            return instance
        }
    })()
    
    const u1 = User.getInstance()
    const u2 = User.getInstance()
    
    console.log(u1 === u2);
    

    方式4

    使用包装对象结合闭包的形式实现

    const User = (function () {
        function _user() {
            this.name = 'xm'
        }
        return function () {
            if (!_user.instance) {
                _user.instance = new _user()
            }
            return _user.instance
        }
    })()
    
    const u1 = new User()
    const u2 = new User()
    
    console.log(u1 === u2); // true
    

    当然这里可以将闭包部分的代码单独封装为一个函数

    在频繁使用到单例的情况下,推荐使用类似此方法的方案,当然内部实现可以采用上述任意一种

    function SingleWrapper(cons) {
        // 排除非函数与箭头函数
        if (!(cons instanceof Function) || !cons.prototype) {
            throw new Error('不是合法的构造函数')
        }
        var instance
        return function () {
            if (!instance) {
                instance = new cons()
            }
            return instance
        }
    }
    
    function User(){
        this.name = 'xm'
    }
    const SingleUser = SingleWrapper(User)
    const u1 = new SingleUser()
    const u2 = new SingleUser()
    console.log(u1 === u2);
    

    方式5

    在构造函数中利用new.target判断是否使用new关键字

    class User{
        constructor(){
            if(new.target !== User){
                return
            }
            if(!User._instance){
                this.name = 'xm'
                User._instance = this
            }
            return User._instance
        }
    }
    
    const u1 = new User()
    const u2 = new User()
    console.log(u1 === u2);
    

    方式6

    使用static静态方法

    class User {
        constructor() {
            this.name = 'xm'
        }
        static getInstance() {
            if (!User._instance) {
                User._instance = new User()
            }
            return User._instance
        }
    }
    
    
    const u1 = User.getInstance()
    const u2 = User.getInstance()
    
    console.log(u1 === u2);
    
    "你的指尖,拥有改变世界的力量! " 欢迎关注我的个人博客:https://sugarat.top
  • 相关阅读:
    Java正则表达式的总结
    Mysql数据库操作语句总结
    Java 如何抛出异常、自定义异常
    Java获取系统时间的四种方法
    Mysql与Oracle区别
    Oracle与MySQL的SQL语句区别
    sql语句的各种模糊查询
    基于SpringCloud的Microservices架构实战案例
    一个人走的快,一群人才走的远
    那些会阻碍程序员成长的细节[2]
  • 原文地址:https://www.cnblogs.com/roseAT/p/14782602.html
Copyright © 2011-2022 走看看