javascript常见的设计模式举例

    近日重读《javascript面型对象编程指南》这本书,最后一章介绍了常见的javascript设计模式的实现。主要讲解了四种设计模式:单例模式、工厂模式、装饰器模式和观察者模式。js作为动态语言,实现这四种模式的实例相对简单,当然既然称之为模式,那么吃透思想更重要,那么下面,由乐帝来实例讲解四种模式。

   1.单例模式

   顾名思义,对象构造出来的是实例,从字面上理解,单例即单实例,这意味一个类只能创建一个实例对象。当需要创建一种类型或者一个类的唯一对象时,可使用该模式。以下两个实例分别从全局变量和类属性两种角度构造单例。属于对象创建型模式。

function Logger(){
	if(typeof global_log==="undefined")
	{
		global_log=this;//没有在函数内定义global_log所以被看成全局变量,并且此时this为window为全局对象
		alert(this);//相当于初始化全局变量并且赋值为window,由于全局变量有唯一性,故可保证单例
	}
	return global_log;//但问题在于全局变量有可能被覆盖掉,造成实例流失
}
var a = new Logger();
var b = new Logger();
console.log(a===b);

//另外一种单例模式:构造器属性
function Logger(){//从面向对象的角度考虑,Logger是一个类
	if(typeof Logger.single_instance==="undefined"){
		Logger.single_instance=this;//Logger.single_instance则是类属性,这个也可以实现单例,类属性和私有属性不同,类属性是类实例公用的
		alert(this);
	}
	return Logger.single_instance;
}

var a=new Logger()
var b=new Logger()
a===b;

           2.工厂模式

   总的来说,工厂模式属于创建对象型模式,当有多个相似对象不知用哪种,可以考虑工厂模式。也属于创建型模式。

//工厂模式
var MYAPP={};
MYAPP.dom={};
MYAPP.dom.Text=function(){
	this.insert=function(where){
		var txt=document.createTextNode(this.url);
		where.appendChild(txt);
	};
};//有三个相似的对象,三个对象中的方法一样,从而使用也一样

MYAPP.dom.Link=function(){
	this.insert=function(where){
		var link=document.createElement('a');
		link.href=this.url;
		linlk.appendChild(document.createTextNode(this.url));
		where.appendChild(link);
	};
};
MYAPP.dom.Image=function(){
	this.insert=function(where){
		var im=document.createElement('img');
		im.src=this.url;
		where.appendChild(im);
	};
};

/* var o=new MYAPP.dom.Image();
 * o.url='www.baidu.com';
 * o.insert(document.body);
 * 
 * var o=new MYAPP.dom.Link();
 * o.url='www.baidu.com';
 * o.insert(document.body);
 * 
 * var o=new MYAPP.dom.Text();
 * o.url='www.baidu.com';
 * o.insert(document.body);
 */
MYAPP.dom.factory=function(type){
	return new MYAPP.dom[type];
}//当构造器过多时,查找不那么一目了然,用工厂函数方法动态操作,省去了如上注释掉的操作或者if操作
var o=MYAPP.dom.factory("Image")//这种方法本质上用到了对象属性的一一对应关系
o.url='www.baidu.com';
o.insert(document.body);

          3.装饰器模式

   此种模式是一种结构型模式,主要考虑如何拓展对象的功能。可以为一个基础对象创建若干装饰器对象以拓展其功能。由我们的程序自行选择不同装饰器,并使用它们。

var tree={};
tree.decorate=function(){
	alert("make sure the tree will not fall");
}
tree.getDecorator=function(deco){
	tree[deco].prototype=this;//返回新对象并且原tree作为新对象的原型对象
	return new tree[deco];
};
tree.RedBalls=function(){//tree的redball属性也是对象
	this.decorate=function(){
		this.RedBalls.prototype.decorate();//首先调用原型对象decorate方法
		alert("put on some red ball");
	}
};

tree.BlueBalls=function(){
	this.decorate=function(){
		this.BlueBalls.prototype.decorate();//首先调用原型对象decorate方法
		alert("add blue ball");
	}
};

tree.Angel=function(){
	this.decorate=function(){
		this.Angel.prototype.decorate();//首先调用原型对象decorate方法
		alert("an angel on the top");
	}
};//以上三个装饰器可按照需要选择
tree=tree.getDecorator("BlueBalls");//返回new tree["BlueBall"],并且保留对tree作为原型对象
tree=tree.getDecorator("RedBalls");//下两个类似
tree=tree.getDecorator("Angel");
tree.decorate();//当调用最后的decorate方法时,会分别上溯调用各自decorate方法中的原型对象方法调用
//装饰器模式的实现,关键在构造新对象时不断保留原对象作为原型对象,同时新对象的方法中,不断调用原型对象的同名方法
//总的来说就是保存原有对象功能的前提下,不断添加新的功能到原有对象

        4.观察者模式

   此种模式属于行为型模式,主要处理对象之间的交互通信的问题。通常包含两类对象:发行商和订阅商。

   

//观察者模式
//观察者模式分为推送和拉动两类,推送模式是由发行商负责将消息通知给各个订阅者,以下为推送模式实例
var observer={//观察这对象
	addSubscriber:function(callback){
		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){
			o[i]=this[i];
			o.subscribers=[];
		}
	}//将任意对象转化为发行商,并赋予以上三种方法,即获取添加、移除订阅者功能以及推送消息功能
};

var blogger={
	writeBlogPost:function(){
		var content='Today is'+new Date();
		this.publish(content);//为成为发行商广播信息做准备的步骤
	}
};
observer.make(blogger);//构造blogger为发行商

var jack={
	read:function (what){
		console.log('I just read that'+what);
	}
};//准备一个潜在订阅者
blogger.addSubscriber(jack.read);//添加订阅者,注意传送的是函数,这样在订阅者publish函数中就能调用订阅者的函数
blogger.writeBlogPost();//发布信息给订阅者
blogger.removeSubscriber(jack.read);//移除订阅者


展开阅读全文

没有更多推荐了,返回首页