可以通过 single.getInstance() 来获取到单例,并且每次调用均获取到同一个单例。这就是 单例模式 所实现的效果。
使用场景:
单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如全局缓存、浏览器的window对象。在js开发中,单例模式的用途同样非常广泛。试想一下,当我们
单击登录按钮的时候,页面中会出现一个登录框,而这个浮窗是唯一的,无论单击多少次登录按钮,这个浮窗只会被创建一次。因此这个登录浮窗就适合用单例模式。
总结一下它的使用场景:
1、可以用它来划分命名空间
2、借助单例模式,可以把代码组织的更为一致,方便阅读与维护
观察者模式(发布订阅模式)
概念:
定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新,也被称为是发布订阅模式。
它需要一种高级的抽象策略,以便订阅者能够彼此独立地发生改变,而发行方能够接受任何有消费意向的订阅者。
应用场景:
这个模式要先说应用场景,比较好理解。
打一个离我们比较近的一个场景,博客园里面有一个订阅的按钮(貌似有bug),比如小A,小B,小C都订阅了我的博客,当我的博客一有更新时,就会统一发布邮件给他们这三个人,就会通知这些订阅者
发布订阅模式的流程如下:
1. 确定谁是发布者(比如我的博客)。
2. 然后给发布者添加一个缓存列表,用于存放回调函数来通知订阅者。
3. 发布消息,发布者需要遍历这个缓存列表,依次触发里面存放的订阅者回调函数。
4、退订(比如不想再接收到这些订阅的信息了,就可以取消掉)
代码如下:
var pubsub = {}; // 定义发布者
(function (q) {
var list = [], //回调函数存放的数组,也就是记录有多少人订阅了我们东西
subUid = -1;
// 发布消息,遍历订阅者
q.publish = function (type, content) {
// type 为文章类型,content为文章内容
// 如果没有人订阅,直接返回
if (!list[type]) {
return false;
}
setTimeout(function () {
var subscribers = list[type],
len = subscribers subscribers.length : 0;
while (len--) {
// 将内容注入到订阅者那里
subscribers[len].func(type, content);
}
}, 0);
return true;
};
//订阅方法,由订阅者来执行
q.subscribe = function (type, func) {
// 如果之前没有订阅过
if (!list[type]) {
list[type] = [];
}
// token相当于订阅者的id,这样的话如果退订,我们就可以针对它来知道是谁退订了。
var token = (++subUid).toString();
// 每订阅一个,就把它存入到我们的数组中去
list[type].push({
token: token,
func: func
});
return token;
};
//退订方法
q.unsubscribe = function (token) {
for (var m in list) {
if (list[m]) {
for (var i = 0, j = list[m].length; i < j; i++) {
if (list[m][i].token === token) {
list[m].splice(i, 1);
return token;
}
}
}
}
return false;
};
} (pubsub));
//将订阅赋值给一个变量,以便退订
var girlA = pubsub.subscribe('js类的文章', function (type, content) {
console.log('girlA订阅的'+type + ": 内容内容为:" + content);
});
var girlB = pubsub.subscribe('js类的文章', function (type, content) {
console.log('girlB订阅的'+type + ": 内容内容为:" + content);
});
var girlC = pubsub.subscribe('js类的文章', function (type, content) {
console.log('girlC订阅的'+type + ": 内容内容为:" + content);
});
//发布通知
pubsub.publish('js类的文章', '关于js的内容');
// 输出:
// girlC订阅的js类的文章: 内容内容为:关于js的内容
// test3.html:78 girlB订阅的js类的文章: 内容内容为:关于js的内容
// test3.html:75 girlA订阅的js类的文章: 内容内容为:关于js的内容
//girlA退订了关于js类的文章
setTimeout(function () {
pubsub.unsubscribe(girlA);
}, 0);
//再发布一次,验证一下是否还能够输出信息
pubsub.publish('js类的文章', "关于js的第二篇文章");
// 输出:
// girlB订阅的js类的文章: 内容内容为:关于js的第二篇文章
// girlC订阅的js类的文章: 内容内容为:关于js的第二篇文章
代码可以自己运行一遍,这样比较好理解
优缺点:
优点:当我们需要维护相关对象的一致性的时候,使用观察者模式,,就可以避免对象之间的紧密耦合。例如,一个对象可以通知另外一个对象,而不需要知道这个对象的信息。
缺点:在发布/订阅模式中,如果我们需要将发布者同订阅者上解耦,将会在一些情况下,导致很难确保我们应用中的特定部分按照我们预期的那样正常工作。也就是说它的优点也可能是它的缺点
策略模式
概念:
策略模式指的是定义一些列的算法,把他们一个个封装起来,目的就是将算法的使用与算法的实现分离开来。说白了就是以前要很多判断的写法,现在把判断里面的内容抽离开来,变成一个个小的个体。
代码实现:
代码情景为超市促销,vip为5折,老客户3折,普通顾客没折,计算最后需要支付的金额。
没有使用策略模式的情况:
function Price(personType, price) {
//vip 5 折
if (personType == 'vip') {
return price * 0.5;
}
else if (personType == 'old'){ //老客户 3 折
return price * 0.3;
} else {
return price; //其他都全价
}
}
不足之处:不好的地方,当我有其他方面的折扣时,又或者我活动的折扣时经常变化的,这样就要不断的修改if..else里面的条件了。而且也违背了设计模式的一个原则:对