设计模式是针对工程中实际的问题总结形成的解决方案,不同的使用场景有对应的解决方案。这些解决方案都遵守 3 个基本原则(单一职责原则(SRP)、开放封闭原则、最少知识原则(LKP))。使用设计模式无疑会增加项目的逻辑复杂度和代码量。所以尤其需要对使用场景进行判断,选择合适的设计模式。然而合理的使用设计模式可以提高项目的可维护性和代码复用性。
多数设计模式在结构上都很类似,区别结构相似的设计模式的要点在于使用的场景、要解决的问题。比如,智能命令模式和策略模式。
不要将静态类型语言和动态类型语言的设计模式混为一谈。两者的语言从根本上就或多或少遵循或违背代码开发的基本原则。Javascript
就天生拥有多态的特性,而C++
中类型固定,才需要抽象又抽象,来解耦对象与类型。设计模式并不局限于语言,在面向对象程序设计语言和函数式语言里都是存在的。
单例模式
可以减少大量重复对象的创建,减少内存的浪费。
JavaScript
中全局变量都就很符合单例(全局仅有一个实例对象,并且全局可访问),不过全局变量命名污染十分严重,还是要尽量少用,最好不用。非用不可的情况,可以用命名空间,用来减少全局变量的数量。或者用闭包封装私有变量。
单例模式主要有两个职责,一个是创建单例对象,另一个是管理单例对象。遵循RSP
原则,应该将创建与管理区分开。
// 创建并管理登录浮窗单例对象耦合在了一起
var createLoginLayer = (function() {
var div = null;
return function() {
if (!div) {
div = document.createElement('div');
div.innerHTML = '登录浮窗';
div.style.display = 'block';
document.body.appendChild(div);
}
return div;
}
})();
/**
* 创建单例对象的话,是有各类各样的,不通用,属于可变的部分。
* 而管理单例是不变的,管理的模式就是用闭包和标志变量来判断处理。
* 抽离管理单例部分为单一函数。 将创建单例对象函数作为参数动态传入。 返回新的函数来管理特定的对象。
*/
function getSingle(fn) {
var result = null;
return function() {
return result || (result = fn.apply(this, arguments));
}
}
// 这儿的参数最后是从 getSingle 返回的新函数返传入的参数,这个 src 只是顺序对,并不是从这个函数传入的。
function createScript (src) { }
var createSingleScript = getSingle(createScript);
function createLoginLayer () { }
var createSingleLoginLayer = getSingle(createLoginLayer);
如果要实现惰性创建单例对象,就需要将创建单例对象的过程放在函数里执行,而不是用IIFE
。