javascript单例模式与策略模式实例详解
作者:flying_huixia
这篇文章主要介绍了javascript单例模式与策略模式,结合实例形式详细分析了javascript单例模式与策略模式基本概念、功能、实现技巧与相关注意事项,需要的朋友可以参考下
一、单例模式
1、概念
保证一个类仅有一个实例,并提供一个访问它的全局访问点
2、单例模式的实现 -- 以创建div节点为例
var createDiv = (function(){
var instance;
var createDiv = function(html){
if(instance){
return instance
}
this.html = html;
this.init();
return instance = this;
};
createDiv.prototype.init = function(){
var div = document.createElement('div');
div.innerHTML = this.html;
document.body.appendChild(div)
}
return createDiv;
})()
var a =new createDiv('one');
var b =new createDiv('two');
console.log(a===b); //true上述例子有缺点:
(1)使用了匿名自执行函数,增加了函数复杂度
(2) createDiv函数做了两件事情,一是创建对象,二是管理单例。违背了单一职责原则
改进--》使用代理实现
//代理模式--改进
//只负责创建div的一个类
var createDiv = function (html) {
this.html = html;
this.init();
};
createDiv.prototype.init = function () {
var div = document.createElement('div');
div.innerHTML = this.html;
document.body.appendChild(div)
}
//引入代理类
var proxySingle = (function(){
var instance;
return function(html){
if(!instance){
instance = new createDiv(html)
}
return instance
}
})();
var a = new proxySingle('one');
var b = new proxySingle('two');
console.log(a === b); //true3、惰性单例(使用)
只在需要的时候才创建对象实例
联系登陆功能的需求,登陆的弹框只会出现一次,在点击点击登陆按钮的时候出现
两种实现
(1)在页面加载完成时,创建好这个浮窗,浮窗一开始是隐藏状态,当用户点击登录的时候,它才开始显示。缺点:会白白浪费一些DOM节点。
(2)当用户点击登陆按钮时才开始创建浮窗:代码如下:
var createLoginer = function(){
var login = document.createElement("div");
login.innerHTML='登录浮窗';
login.style.display = 'none';
document.body.appendChild(login);
return login
}
//点击登陆按钮
btn.onclick = function(){
var loginer = createLoginer();
loginer.style.display = 'block';
}现在惰性的目的达到了,但失去了单例的效果--》再次修改如下:
用一个变量判断是否已经创建过登录浮窗
//创建登陆浮窗
var createLoginer = function () {
var login = document.createElement("div");
login.innerHTML = '登录浮窗';
login.style.display = 'none';
document.body.appendChild(login);
return login
}
var loginer;
var getSingle = function (fn) {
return function () {
console.log(this)
return loginer || (loginer = fn.apply(this))
}
}
//createSingleLoginer接下来作为函数调用,所以getSingle得返回一个函数,并且这个函数得返回登录浮窗
var createSingleLoginer = getSingle(createLoginer);
//点击登陆按钮
var btn = document.getElementById("btn");
btn.onclick = function () {
var loginer = createSingleLoginer();
loginer.style.display = 'block';
}getSingle就是用来管理单例的
惰性单例:只有在合适的时候才创建对象,并只创建唯一的一个。把创建对象和管理单例的职责分布在不同的方法中,组合起来才能发挥真正的单例模式的威力。
二、策略模式
1、概念:
定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换
2、实例
发年终奖,按照等级和各自的基础工资进行乘积运算
var strage = {
S:function(salary){
return salary*4
},
A:function(salary){
return salary*3
},
B:function(salary){
return salary*2
}
}
var calculateBounus = function(level,salary){
return strage[level](salary)
};
console.log(calculateBounus('S',2000)) //8000
console.log(calculateBounus('A',2000)) //60003、策略模式用来封装算法,更广义的使用,表单验证登录算法
把校验方式封装成策略对象
var validatorFunc = function () {
var validator = new Validator();
validator.add(loginForm.userName, "isEmpty", '用户名不能为空')
validator.add(loginForm.passWord, "minLength:6", '密码长度不能少于6位')
validator.add(loginForm.phone, "phoneValidator", '手机号码格式错误')
var errMsg = validator.start();
return errMsg
}
var loginForm = document.getElementById("login")
function login() {
var errMsg = validatorFunc();
if (errMsg) {
alert(errMsg);
return false; //阻止表单提交
}
}
var Validator = function () {
//缓存校验规则
this.cache = [];
}
Validator.prototype.add = function (dom, rule, err) {
var ary = rule.split(':');
this.cache.push(function () {
var strategy = ary.shift();
ary.unshift(dom.value);
ary.push(err)
return loginStrage[strategy].apply(dom, ary)
})
}
Validator.prototype.start = function () {
for (var i = 0; i < this.cache.length; i++) {
var err = this.cache[i]()
if (err) {
alert(err)
}
}
}运行页面:
