前言
最近在看javascript设计模式与开发实践,虽然之前就看过一部分,但是缺乏记录到最后也忘得7788了,这次要好好看好好记好好学
单例模式是啥
先来看看定义。
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
现实中的单例子模式
function Card(money) {
this.money = money;
}
Card.prototype.getMoney = function(){
console.log(this.money);
}
const card = new Card(500);
card.getMoney(); //500
但是一段时间过后,小明忘记了卡在哪里了,只能又去办了一张卡,又浪费了500块。
function Card(money) {
this.money = money;
}
Card.prototype.getMoney = function(){
console.log(this.money);
}
const card = new Card(500);
card.getMoney(); //500
const card2 = new Card(500);
card2.getMoney(); //500
console.log(card === card2); //false
会员卡,小明只需要一张就够了,办了两张,浪费资源,并且发廊也做的不好,应该根据手机号或者身份证等记录下卡的信息。
后来老板找技术人员小强引进了新的系统,可以判断你是否办过卡,如果办过了就直接可以使用已经办了的卡,这时候就用到了单例模式。再也不怕我的会员卡丢了。
const Card = (function () {
let instance;
return function Card(money) {
if (instance) return instance;、//老哥你已经办过卡了
this.money = money;
instance = this;
}
})()
Card.prototype.getMoney = function () {
console.log(this.money);
}
const card = new Card(500);
card.getMoney(); //500
const card2 = new Card(500); //老哥不用了,你上次办的卡还有500块呢
card2.getMoney(); //500
console.log(card === card2); //true
这个系统还有点小bug,帮客人办卡之前,一定要点一下new,否则会出错,店员老是忘记,导致很多客人数据丢失了
const Card = (function () {
let instance;
return function Card(money) {
if (instance) return instance;
this.money = money;
instance = this;
}
})()
Card.prototype.getMoney = function () {
console.log(this.money);
}
const card = Card(500);
card.getMoney(); //Uncaught TypeError: Cannot read property 'getMoney' of undefined
//老子的钱呢??
后面又找了技术人员小强帮忙搞了一下。
const Card = (function () {
let instance;
return function Card(money) {
if (!(this instanceof Card)) throw("new啊!再不记得扣工资了"); //这里当然也可以返回new Card(money)
if (instance) return instance;
this.money = money;
instance = this;
}
})()
Card.prototype.getMoney = function () {
console.log(this.money);
}
const card = Card(500);
card.getMoney();
这下店员如果不记得点下new,帮客人办会员卡的时候,就会弹出错误了。这下稳了
通用单例
技术人员小强因为接了发廊项目,赚了点小钱,而且越来越多商家找小强搞系统,小强都不想在公司996搬砖了。但是商家太多啊,根本忙不过来,请人又要分一杯羹。有啥办法呢?于是小强又改进了一下系统
const superCard = function(fn){
if(Object.prototype.toString.call(fn) !== "[object Function]")throw "请正确传入函数";
let instance;
return function superCard(...params){
if(!(this instanceof superCard))throw "请点new";
return instance?instance:instance = new fn(...params);
}
}
把判断是否办过卡的逻辑抽出来封装好,可以使用于各种商铺,不管你是理发店还是便利店还是洗脚店。
const superCard = function(fn){
if(Object.prototype.toString.call(fn) !== "[object Function]")throw "请正确传入函数";
let instance;
return function superCard(...params){
if(!(this instanceof superCard))throw "请点new";
return instance?instance:instance = new fn(...params);
}
}
const Barber = function(money){
this.money = money;
}
Barber.prototype.getMoney = function(){
console.log(this.money);
}
const SuperBarber = superCard(Barber);
const card = new SuperBarber(500);
const card2 = new SuperBarber(500);
card.getMoney(); //500
card2.getMoney(); //500
console.log(card === card2); //true
现在小强已经实现了财富自由,赢取白富美,走上人生巅峰。。。。。。
前端中的应用
回到前端,因为js是一门无类语言,所有的类都是想方设法仿出来的,在js中创建对象非常简单,所以实现最简单的单利模式就是创建一个全局变量,唯一的,全局都能访问的对象。但是全局变量还是要减少使用,我们可以通过命名空间和私有变量等方式去减少对全局变量的使用。
命名空间
var MyApp = {};
MyApp.namespace = function (name) {
var parts = name.split('.');
var current = MyApp;
for (var i in parts) {
if (!current[parts[i]]) {
current[parts[i]] = {};
}
current = current[parts[i]];
}
};
MyApp.namespace('event');
MyApp.namespace('dom.style');
私有变量
var user = (function () {
var __name = 'sven',
__age = 29;
return {
getUserInfo: function () {
return __name + '-' + __age;
}
}
})();
vuex中的单例模式
保证一个vue实例只会被install一次Vuex插件,这就是单例模式的运用了
我们常用的react中的状态管理redux中的store也是唯一的,且所有组件都有办法去和它进行数据的交互。又例如前端页面常用的对话框,状态栏,基本也都是一个单例模式,全局只需要一个。这些都是单例模式的体现