瓜籽儿的Blog

专注于JavaScript技术!努力用最简单的办法去解决最复杂的问题!

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

JavaScript设计模式之装饰者模式

Posted on 2010-04-16 17:35  瓜籽  阅读(353)  评论(0编辑  收藏  举报

    JS的设计模式我看了很久一直都没有弄明白但总觉得这个模式对以后的工作是会有所帮助的。找了些资料来看越看越糊涂;越看越不知道该怎么弄。昨天在网上看到Leepy关于“装饰者”的一篇文章后,让我有所明白了其中的一些道理。关于“装饰者模式”的思路我想还是和上一篇“观察者模式”的思路一样,将死板的程序变为现实中的实例。这样可以加深记忆,帮助理解(这只是我自己的记忆方法,大家可以根据自己的情况来决定 ^_^)。

    我想把这次的“装饰者模式”看做是“演员”和“电影公司”的关系。这个要怎么理解呢?我来捋一下思路:

    1、演员从电影学院毕业后,自身就具备了表演、唱歌、朗诵、跳舞等一些表演本领;现在需要一个电影公司(装饰者)来包装(装饰)他们(被装饰的对象)。

    2、做电影的公司都要具备的条件(所有电影公司必须具备的接口)是可以针对演员自身的条件来对其做进一步的深加工,将他们二次包装(装饰)并推向市场以获得收益。

    3、电影公司多如牛毛,但他们都必须具备深加工演员的资本(继承接口中的方法)。当有演员加盟到这个电影公司后,他们可以通过这些必备的接口来对演员进行包装(装饰)。

    4、在包装(装饰)的过程中,可能对演员本身的一些特点做了一些扩大或是将这些特点用一些其他的手段施放出来,让市场对他们有一个新的认识。比如说这个演员单枪匹马在社会中闯的话,他的身价只是100元;但经过电影公司的包装(装饰)后,他的身价已经涨到10000元了。这就是包装(装饰)的效果。

 

    下面就来具体的看一下电影公司(装饰者)和演员(被装饰者)在现实代码中是如何定义的。

    一、演员毕业步入社会,即已经有了一个完整的被装饰者。他已经具备了某些功能现在需要被装饰(包装)。

// 我是一个演员,我有“表演”,“唱歌”,“跳舞”和“朗诵”的本事。现在需要一个电影公司来包装我。
function Actor(){
	// 可以有一些属性
};
Actor.prototype = {
	// “表演”的功能
	getPerformacne : function(){
		return '我会表演!';
	},
				
	// “表演”的功能
	getSinging : function(){
		return '我会唱歌!';
	},
				
	// “跳舞”的功能
	getDance : function(){
		return '我会跳舞!';
	},
				
	// “朗诵”的功能
	getSpeech : function(){
		return '我会朗诵!';
	},
				
	// 演员的出场费
	getPrice : function(){
		return 100;
	}
};

 

    二、所有电影公司都需要具备的条件(用以装饰演员)

// 所有电影公司都要具备的条件
function FilmCompany(actor){
	this.actor = actor;
	// 可以做一个接口检查,来判断这个演员(actor)是否已经具备了这些功能。接口检查在这里我就没有写了,留给大家自己去处理了。
};
			
// 每个电影公司都要具备的包装演员的方法
FilmCompany.prototype = {
	// 具有包装演员(actor)的表演能力
	getPerformacne : function(){
		return this.actor.getPerformacne();
	},
				
	// 具有包装演员(actor)的唱歌能力
	getSinging : function(){
		return this.actor.getSinging();
	},
				
	// 具有包装演员(actor)的跳舞能力
	getDance : function(){
		return this.actor.getDance();
	},
				
	// 具有包装演员(actor)的朗诵能力
	getSpeech : function(){
		return this.actor.getSpeech();
	},
				
	// 具有包装演员(actor)的出场费
	getPrice : function(){
		return this.actor.getPrice();
	}
};

    三、出现不同的电影公司,他们用来包装各自加盟的演员

// 我是众多电影公司中的一个。我叫ChinaMovie
function ChinaMovie(actor){
	FilmCompany.call(this, actor);
};
extend(ChinaMovie, FilmCompany);

// 装饰了演员的朗诵功能			
ChinaMovie.prototype.getSpeech = function(){
	return this.actor.getSpeech()+'我现在朗诵的是:《黄河颂》';
};

// 提升了演员的价值 				
ChinaMovie.prototype.getPrice = function(){
	return this.actor.getPrice()*100;	//	此种做法为:在被装饰者方法之后添加行为。
};

//******************************************* 华丽分隔线 ******************************************//

// 我是众多电影公司中的一个。我叫USAMovie
function USAMovie(actor, color){
	FilmCompany.call(this, actor);
	this.hairColor = color;	//	此种做法为:在被装饰者方法之前添加行为。
};
extend(USAMovie, FilmCompany);

// 装饰了演员的跳舞功能			
USAMovie.prototype.getDance = function(){
	return this.actor.getDance()+'我现在跳的舞是:《黄河之舞》';
};

// 提升了演员的价值			
USAMovie.prototype.getPrice = function(){
	return this.actor.getPrice()*10000;
};

// 通过演员的表演功能来改变演员头发的颜色,工作的需要		
USAMovie.prototype.getPerformacne = function(){
	return '我现在头发的颜色是:' + this.hairColor;
};

 

    四、现在就要将“演员”与“电影公司”联系起来,从而达到“装饰者”的功能。

var actor = new Actor();	// 独立的演员
var zhActor = new ChinaMovie(actor);	// 经ChinaMovie电影公司包装后的演员
var enActor = new USAMovie(actor, '黄色');	// 经USAMovie电影公司包装后的演员

// 也可以中西合并也就是说可以由一个电影公司包装后再由另外一家二次包装,且将其两者合二为一。
var mixActor = new Actor();
mixActor = new ChinaMovie(mixActor);
mixActor = new USAMovie(mixActor, '黄色');

 

    以上就已经完成了包装。将一个演员经过不同的电影公司装饰后展示给大家的是一个不一样个体,由一个独立的演员到中国(美国)大腕儿的转变。装饰者模式的好处在于不改变原有演员基本特性的基础上,在外围对其进行扩展,从而达到预期的目的。在这里我可能有些理解错误的地方,还希望大家踊跃拍砖,呵呵~~ 下面是一个相对完整的例子: