前端设计模式(2)--单例模式

栏目: 后端 · 发布时间: 5年前

内容简介:单例就是保证一个类只有一个实例,实现方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。但是有个问题:违反了单一职责原则,不够清晰,所以需要改进一下现在是清晰了,但是还有一个小问题,Window给写死了,作为一个优秀的程序员,肯定要灵活,来来再改进一下。

单例就是保证一个类只有一个实例,实现方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。

代码

单例模式的简单实现

es5

function Window(name) {
    this.name = name;
}
Window.prototype.getName = function () {
    return this.name;
}

//这是类上的方法,只可以通过类来访问,而不能通过实例来访问
Window.getInstance = (function () {
    let instance;
    return function (name) {
        if (!instance) {
            instance = new Window(name);
        }
        return instance;
    }
})();

let w1 = Window.getInstance();
let w2 = Window.getInstance();

console.log(w1 === w2) // --> true 
复制代码

es6

class Window {
    constructor(name) {
        this.name = name;
    }
    static getInstance() {
        if (!this.instance) {
            this.instance = new Window();
        }
        return this.instance;
    }
}
let w1 = Window.getInstance();
let w2 = Window.getInstance();
console.log(w1 === w2)
复制代码

缺点:

  1. 客户端 就是使用这个类的使用者必须知道这是一个单例的类,必须主动调用getInstance方法,使用麻烦
  2. 并不能真正阻止客户端直接new Window
let w3 = new Window();
let w4 = new Window();
复制代码

优化过程

透明单例

//透明单例
let Window = (function () {
    let window;
    let Window = function (name) {
        if (window) {
            return window;
        } else {
            this.name = name;
            return (window = this);
        }
    }
    return Window;
})();
let w1 = new Window();
let w2 = new Window();
console.log(w1 === w2);
复制代码
  1. 创建一个this=空对象
  2. new 关键字,如果返回的是一个对象,那么返回对象

但是有个问题:违反了单一职责原则,不够清晰,所以需要改进一下

//把类的实例的创建逻辑和单例逻辑分开
function Window(name) {
    this.name = name;
}
Window.prototype.getName = function () {
    console.log(this.name);
}


let CreateWindow = (function () {
    let instance;
    return function (name) {
        if (!instance) {
            instance = new Window(name);
        }
        return instance;
    }
})();
let w1 = new CreateWindow('zfpx1');
let w2 = new CreateWindow('zfpx2');
console.log(w1 === w2);
复制代码

现在是清晰了,但是还有一个小问题,Window给写死了,作为一个优秀的程序员,肯定要灵活,来来再改进一下。

function Window(name) {
    this.name = name;
}
Window.prototype.getName = function () {
    console.log(this.name);
}


let CreateWindow = (function () {
    let instance;
    return function (name) {
        if (!instance) {
            instance = new Window(name);
        }
        return instance;
    }
})();
let w1 = new CreateWindow('zfpx1');
let w2 = new CreateWindow('zfpx2');
console.log(w1 === w2);
复制代码

命名空间

1.变量名冲突

2.复杂层次对象的可读性要求

其实我们之前用的jquery并没有把变量都声明在 window上,而是都挂在$对象 jQuery,来,栗子两枚:

$.get();
$.post();
$.ajax();
let $ = {
  ajax(){},
  get(){},
  post(){}
}


let $ = {};
$.define = function (namespace, fn) {
    let namespaces = namespace.split('.');
    let fnName = namespaces.pop();
    let current = $;
    for (let i = 0; i < namespaces.length; i++) {
        let namespace = namespaces[i];//dom
        if (!current[namespace]) {
            current[namespace] = {};//{dom:{}}
        }
        current = current[namespace];
    }
    current[fnName] = fn;
}
$.define('dom.class.addClass', function () {
    console.log('dom.class.addClass');
});
$.define('dom.attr', function () {
    console.log('dom.attr');
});
$.define('string.trim', function () {
    console.log('string.trim');
});
console.log($) // define、dom、string都挂载上了了
$.dom.class.addClass('title'); // -> dom.class.addClass
$.dom.attr('src'); // -> dom.attr
$.string.trim(' abc '); // -> string.trim

复制代码

单例模式的应用场景

jQuery

只会有一个jQuery实例

if(window.jQuery!=null){
  return window.jQuery;
}else{
    //init~~~~~~~
}
复制代码

模态窗口

一般网站都会有用户系统,例如我们去淘宝买东西,第一时间需要你先登录

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <button id="show-btn">显示登录框</button>
    <button id="hide-btn">隐藏登录框</button>
    <script>
        class Login {
            constructor() {
                this.element = document.createElement('div');
                this.element.innerHTML = (
                    `
                     用户名 <input name="username"/>
                     密码 <input name="password"/>
                     <input type="submit" value="登录"/>
                    `
                );
                this.element.style.cssText = `width:100px;height:100px;position:absolute;left:50%;top:50%;margin-top:-50px;margin-left:-50px;display:none`;
                document.body.appendChild(this.element);
            }
            show() {
                this.element.style.display = 'block';
            }
            hide() {
                this.element.style.display = 'none';
            }
            static getInstance() {
                if (!this.instance) {
                    this.instance = new Login();
                }
                return this.instance;
            }
        }
        document.getElementById('show-btn').addEventListener('click', function () {
            Login.getInstance().show();
        });
        document.getElementById('hide-btn').addEventListener('click', function () {
            Login.getInstance().hide();
        });
    </script>
</body>

</html>
复制代码

store

redux 整 个应用只有一个仓库,整 个仓库只有一个状态state

//redux 整 个应用只有一个仓库,整 个仓库只有一个状态state
function createStore(reducer) {
    let state;
    let listeners = [];
    function subscribe(listener) {
        listeners.push(listener);
    }
    function getState() {
        return state;
    }
    function dispatch(action) {
        state = reducer(state, action);
    }
    return {
        getState,
        dispatch,
        subscribe
    }
}

let reducer = function () {

}
let store = createStore(reducer);
复制代码

今天写到这里,喜欢的可以点赞,同时欢迎抛转,有空再写下总结吧~


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Kotlin实战

Kotlin实战

【美】Dmitry Jemerov(德米特里·詹莫瑞福)、【美】 Svetlana Isakova(斯维特拉娜·伊凡诺沃) / 覃宇、罗丽、李思阳、蒋扬海 / 电子工业出版社 / 2017-8 / 89.00

《Kotlin 实战》将从语言的基本特性开始,逐渐覆盖其更多的高级特性,尤其注重讲解如何将 Koltin 集成到已有 Java 工程实践及其背后的原理。本书分为两个部分。第一部分讲解如何开始使用 Kotlin 现有的库和API,包括基本语法、扩展函数和扩展属性、数据类和伴生对象、lambda 表达式,以及数据类型系统(着重讲解了可空性和集合的概念)。第二部分教你如何使用 Kotlin 构建自己的 ......一起来看看 《Kotlin实战》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码