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
  • 相关阅读:
    Shared Memory in Windows NT
    Layered Memory Management in Win32
    软件项目管理的75条建议
    Load pdbs when you need it
    Stray pointer 野指针
    About the Rebase and Bind operation in the production of software
    About "Serious Error: No RTTI Data"
    Realizing 4 GB of Address Space[MSDN]
    [bbk4397] 第1集 第一章 AMS介绍
    [bbk3204] 第67集 Chapter 17Monitoring and Detecting Lock Contention(00)
  • 原文地址:https://www.cnblogs.com/roseAT/p/14782602.html
Copyright © 2011-2022 走看看