一、单例设计模式(Singleton Pattern)
单例模式也称为单子模式,单体模式。它的定义是产生一个类的唯一实例,是工作中常用的一种设计模式。
可以用创建对象的方式来实现单例模式。
var obj = {
xxx: xxx
};
var pattren1 = { name: 'xxx' };
var pattern2 = { name: 'xxx' };
我们知道对象数据类型的作用是把描述同一个事物(同一事件)的属性和方法放在一个内存空间下,起到分组的作用,这样不同的事物之间的属性即使属性名相同,相互间也不会发生冲突。
在单例模式中,obj它不仅仅是对象名,它还被称为“命名空间(NameSpace)”,每一个命名空间都是js中Object这个内置类的实例,相互之间不干扰,所以称之为“单例”即“单独的实例”。
从上面对象数据类型的作用我们可得知单例模式它是把描述同一件事的属性和特征进行了“分组,归类(存在同一堆内存空间中)”,因此避免了全局变量之间的冲突和污染。
上面那种对象字面量创建方式一般不常用,因为它没有什么封装性,属性和方法暴露且对象一开始就创建,如果用不上,那就是一种浪费。所以我们一般利用自执行函数来实现。
var nameSpace = (function () {
var n = 12;
function fn() {
//......
}
functon sum() {
//......
}
return {
fn: fn,
sum:sum
}
})();
可看到在给命名空间赋值时,不是直接赋值一个对象而是先执行匿名函数,形成一个私有作用域,在私有作用域中创建一个堆内存,把堆内存地址赋值给命名空间。这样做我们可以在私有作用域中创造很多的内容(变量或函数)哪些需要供外面使用就把它return出去。简单来说,nameSpace它指的是返回的对象(return后的内容),自执行函数形成一个不销毁的栈内存把返回结果赋值给nameSpace。
范例:
var n = 2;
var obj = {
n: 3,
fn: (function (n) {
n *= 2;
this.n += 2;
var n = 5;
return function (m) {
this.n *= 2;
console.log(m + (++n));
}
})(n)//=>obj.n会报错
};
var fn = obj.fn;
fn(3);
obj.fn(3);
console.log(n, obj.n);
二、工厂模式(Factory Pattern)
单例模式虽然解决了分组问题,但是它不能“批量生产”,所以有了工厂模式。把实现同一件事的相同的代码放到一个函数中,以后如果再想实现这个功能,不需要重新的编写代码,只需要执行当前的操作就可。
function createPerson(name, age) {
let obj = {};
obj.name = name;
obj.age = age;
obj.personInf = function () {
console.log('我的名字是' + this.name + ',今年' + this.age + '岁');
}
return obj;
}
let p1 = createPerson('davina', 12).personInf();
console.log(p1, p2);//我的名字是davina,今年12岁
从中我们可以简单的看出工厂模式的优点:在工厂模式中,我们只需要知道所要生产的具体的东西,无须关心具体的创建过程,如果增加新的产品时,只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何的修改,很好的符合了"开闭原则"。
不足:每增加一个产品的时候都需要增加一个具体的类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。