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
  • 相关阅读:
    使用RestTemplate进行服务调用的几种方式
    springmvc学习指南 之---第32篇 mybatis 嵌套的处理
    springmvc学习指南 之---第31篇 使用墨客进行测试报错
    springmvc学习指南 之---第30篇 异常的全局处理
    Effective Java 阅读笔记--之(一) 建造者模式(Builder)
    使用mybatis-generator.xml 生成PO 对象
    springmvc学习指南 之---第29篇 springmvc 返回json对象, 不想创建类的前提下
    springmvc学习指南 之---第28篇 springmvc的controller 如何解析视图view? 如何解析json,html,jsp?
    springmvc学习指南 之---第27篇 spring如何实现servlet3.0无web.xml 配置servlet对象的
    springmvc学习指南 之---第26篇 在idea中如何debug跟踪到tomcat内部代码
  • 原文地址:https://www.cnblogs.com/roseAT/p/14782602.html
Copyright © 2011-2022 走看看