JS设计模式笔记(单例和策略)

单例模式

单例模式的核心是确保只有一个实例,并提供全局访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var getSingle = function(fn) {
var result;
return function() {
return result || (result = fn.apply(this, arguments));
}
};

// 实例
var createLoginLayer = function() {
var div = document.createElement('div');
div.innerHTML='我是登录框';
div.style.display = 'none';
document.body.appendChild(div);
return div;
};

var createSingleLoginLayer = getSingle(createLoginLayer);

document.getElementById('test').onlick = function() {
var loginLayer = createSingleLoginLayer();
loginLayer.style.display = 'block';
};

创建实例对象的职责和管理单例的职责分别放置在2个方法里,这两个方法可以独立变化而互不影响

策略模式

策略模式的目的是将算法的使用和算法的实现分离

一个基于策略模式的程序至少有两部分组成.

  1. 一组策略类,策略类封装了具体的算法,并负责具体的计算过程
  2. 环境类Context, Context接受客户请求,随后把请求委托给某一策略类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// ----------实例一 计算奖金----------

var strategies = {
'S': function(salary) {
return salary * 4;
},
'A': function(salary) {
return salary * 3;
},
'B': function(salary) {
return salary * 2;
}
};

var calculateBonus = function(level, salary) {
return strategies[level](salary);
};

console.log(calculateBonus('S', 20000));

calculateBonus并没有计算奖金的能力,而是把这个职责委托给了某个策略对象,每个策略对象负责的算法已经被各自封装在对象内部了


策略模式也可以用来封装一系列”业务规则”.只要这些业务规则指向的目标一致,并且可以被替换使用,就可以使用策略模式封装它们;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 实例二 表单校验

var strategies = {
isNonEmpty: function(value, errMsg) {
if (value === '' || value === undefined || value === null) {
return errMsg;
}
},
minLen: function(value, len, errMsg) {
if (value.length < len) {
return errMsg;
}
}
};

var Validator = function() {
this.cache = [];
};

Validator.prototype.add = function(value, rules) {
var _this = this;
for (var i = 0, rule; rule = rules[i]; i++) {
(function(rule) {
var strategyArr = rule.strategy.split(':');
var ruleName = strategyArr.shift();
strategyArr.unshift(value);
strategyArr.push(rule.errMsg || (rule + '错误'));
_this.cache.push(function() {
return strategies[ruleName].apply(null, strategyArr);
});
})(rule);
}
};

Validator.prototype.start = function() {
for (var i = 0, validatorFun; validatorFun = this.cache[i]; i++) {
var errMsg = validatorFun();
if (errMsg) {
return errMsg;
}
}
};

function checkreg(userName) {
var validator = new Validator();
validator.add(userName, [{
strategy: 'isNonEmpty',
errMsg: '用户名不能为空'
}, {
strategy: 'minLen:3',
errMsg: '最小长度为3'
}]);
var errMsg = validator.start();
console.log(errMsg);
}

checkreg(''); // 用户名不能为空
checkreg('aa'); // 最小长度为3

策略模式的优点

  1. 策略模式利用 组合,委托和多态等技术和思想,可以有效的避免多重条件选择语句
  2. 策略模式提供了对开方-封闭原则的完美支持,将算法封装在独立的strategy中,使得他们易于切换,易于理解,易于扩展
  3. 策略模式的算法也可以复用在系统的其他地方,从而必选许多重复的复制粘贴工作
  4. 在策略模式中利用组合和委托来让Context拥有算法的执行能力,这也是继承的一种更轻便的替代方案

策略模式的缺点

  1. 增加了许多策略类/策略对象
  2. 必须了解所有的strategy,知道其不同点

参考文档

  • 实体书: JavaScript设计模式与开发实践(曾探)

文章若有纰漏请大家补充指正,谢谢~~
http://blog.xinshangshangxin.com SHANG殇