Javascript的设计模式
设计模式基本可以分为三组模式:
- 创建型模式:设计对象的创建与初始化
- 结构型模式:描述了如何组合对象以提供新的功能
- 行为型模式:描述了对象之间如何通信
本次主要讲解四个模式,即:
- 单件模式
- 工厂模式
- 装饰器模式
- 观察者模式
一、单件模式
1.单件模式1
最简单的单件模式就是利用对象文本标识法:
var single = {};
2.单件模式2
① 利用全局变量:
function Logger () {
if (typeof global_log === "undefined") {
global_log = this;
}
return global_log;
}
// 定义两个构造器,并比较
var a = new Logger();
var b = new Logger();
console.log(a === b); // true
② 利用构造器属性
function Logger () {
if (!Logger.single_instance) {
Logger.single_instance = this;
}
return Logger.single_instance;
}
③ 使用私有属性
var Logger = (function () {
var private = this;
return function () {
return private;
}
})()
二、工厂模式
当我们有多个相似的对象而又不知道应该使用哪一种的时候,
可以考虑使用工厂模式,根据输入自行决定创建哪一种对象
var myApp = {};
myApp.dom = {};
myApp.dom.Text = function (url) {
this.url = url;
this.insert = function (where) {
var txt = document.createTextNode(this.url);
where.appendChild(txt);
};
};
myApp.dom.Link = function (url) {
this.url = url;
this.insert = function (where) {
var link = document.createElement('a');
link.href = this.url;
link.appendChild(document.createTextNode(this.url));
where.appendChild(link);
};
};
myApp.dom.Image = function (url) {
this.url = url;
this.insert = function (where) {
var im = document.createElement('img');
im.src = this.url;
where.appendChild(im);
};
};
var url = 'http://www.baidu.com/logo.jpg';
var o = new myApp.dom.Image(url);
o.insert(document.body);
var o = new myApp.dom.Text(url);
o.insert(document.body);
var o = new myApp.dom.Link(url);
o.insert(document.body);
当我们写一个库或者框架时,可以考虑委托给一个工厂函数:
myApp.dom.factory = function (type, url) {
return new myApp.dom[type](url);
};
var url = 'http://...'
var image = myApp.dom.factory("image", url);
image.insert(document.body);
三、装饰器模式
装饰器模式是一种结构型模式,它与对象创建无关,主要考虑的是如何拓展对象的功能。也就是说,除了使用线性式(父-子-孙)继承方式之外,我们也可以为一个基础对象创建若干个装饰对象以拓展其功能。
以下为具体实例:
var tree = {};
tree.decorate = function () {
alert('Make sure the tree won\'t fall');
};
// getDecorate函数会创建一个原型为tree的新实例
tree.getDecorate = function (deco) {
tree[deco].prototype = this;
return new tree[deco];
};
tree.RedBalls = function () {
this.decorate = function () {
this.RedBalls.prototype.decorate();
alert('Put on some red balls');
};
};
tree.BlueBalls = function () {
this.decorate = function () {
this.BlueBalls.prototype.decorate();
alert('Add blue balls');
};
};
tree.Angel = function () {
this.decorate = function () {
this.Angel.prototype.decorate();
alert('An angel on the top');
};
};
// 把所有装饰器添加到基础对象中
tree = tree.getDecorate('BlueBalls');
tree = tree.getDecorate('RedBalls');
tree = tree.getDecorate('Angel');
// 运行decorate()
tree.decorate();//按顺序弹出4个提示
四、观察者模式
观察者模式(也成为发布-订阅模式)是一种行为型模式,主要用于处理不同对象之间的交互通信问题。
观察者模式中通常会包含两类对象:
- 一个或多个发布者对象:当有重要的事情发生时,会通知订阅者。
- 一个或多个订阅者对象:它们追随一个或多个发布者,监听他们的通知,并作出相应的反应
观察者对象应该有如下的属性和方法:
- 由回调函数构成的订阅者数组
- 用于添加和删除订阅者的addSubscriber()和removeSubscriber()方法。
- publish()方法,接受并传递数据给订阅者。
- make()方法,讲任意对象转变为一个发布者并为其添加上述方法。
以下是一个实现代码:
var observer = {
// 添加订阅者
addSubscriber: function (callback) {
if (typeof callback === 'function') {
this.subscribers[this.subscribers.length] = callback;
}
},
// 删除订阅者
removeSubscriber: function (callback) {
for (var i = 0; i < this.subscribers.length; i++) {
if (this.subscribers[i] === callback) {
delete this.subscribers[i];
}
}
},
// 发布消息,出发回调函数
publish: function (what) {
for (var i = 0; i < this.subscribers.length; i++) {
if (typeof this.subscribers[i] === 'function') {
this.subscribers[i](what);
}
}
},
// 创建发布者
make: function (o) {
for (var i in this) {
if (this.hasOwnProperty(i)) {
o[i] = this[i];
o.subscribers = [];
}
}
}
}
// 创建两个发布者
var blogger = {
writeBlogPost: function () {
var content = 'Today is ' + new Date();
this.publish(content);
}
};
var la_times = {
newIssue: function () {
var paper = 'Martians have landed on Earth!';
this.publish(paper);
}
};
observer.make(blogger);
observer.make(la_times);
// 创建两个订阅者
var jack = {
read: function (what) {
console.log("I just read that " + what);
}
};
var jill = {
gossip: function (what) {
console.log("You didn't hear it from me, but " + what);
}
};
blogger.addSubscriber(jack.read);
blogger.addSubscriber(jill.gossip);
// 发布者触发函数
blogger.writeBlogPost();
// jack与jill都会收到通知,控制台打印消息
// 任何时候都可以取消订阅
blogger.removeSubscriber(jill.gossip);
la_times.addSubscriber(jill.gossip);
la_times.newIssue();