我爲何把他們兩個放在一塊兒講?我以爲這兩個設計模式有類似之處,有時候會一個設計模式不能知足你的需求而採用另外一種設計模式。基於這點考慮,並且爲了你們更好地理解,我放到了一塊兒,加深你們的印象,活學活用。編程
[這裏我爲了能更好的體現下設計模式與JS本體語言的結合,我用了一點繼承關係.
有的同窗都不知道JS能繼承,就算你們不懂繼承也但願你們能看下去,弄懂它!]
複製代碼
掘金有個文章繼承仍是蠻透徹的 JS原型鏈與繼承別再被問倒了後端
在咱們Team協做開發過程中,不一樣於咱們寫我的項目,對全局變量的限制很大,咱們要儘可能少的使用全局變量,對於一類對象在不一樣需求上的不一樣使用,甚至將一些有些相似的方法抽象化,能夠用工廠模式來負責建立這些對象,調用者可使用一部分資源也能夠在基礎上私人訂製一套資源。設計模式
就拿昨天入羣的小夥伴舉個栗子:他設計一個網頁播放器有四個按鈕:bash
咱們不討論他的實現方式,咱們按照工廠模式來簡單建立一個吧!框架
function wangyiMusicAction(action){
var o = new Object;
o.vender = '網易雲音樂';
o.playingMusic = 'see you again'
switch (action){
case 'last':
o.information = {currentMusic:'Ich will',status:'200|404',message:'上一曲'}
break
case 'next':
o.information = {currentMusic:'一人我編程累',status:'200|404',message:'下一曲'}
break
case 'play':
o.information = {currentMusic:'see you again',status:'200|500',message:'播放'}
break
case 'mute':
o.information = {currentMusic:'see you again',status:'200|500',message:'靜音'}
break
}
return o;
}
var music = wangyiMusicAction('next')
console.log('音樂提供商 : '+music.vender);
console.log('正在播放 : '+music.playingMusic);
console.log('執行動做 : ' +music.information.message);
console.log('接口狀態 : ' +music.information.status);
console.log('執行動做後歌曲 : ' +music.information.currentMusic);
----------執行結果--------
音樂提供商 : 網易雲音樂
正在播放 : see you again
執行動做 : 下一曲
接口狀態 : 200|404
執行動做後歌曲 : 一人我編程累
複製代碼
這其實使咱們常用的,不過這是面向過程的,不太符合咱們的設計模式。咱們用上篇學到的模式:對象
函數
咱們能夠修改一下:ui
var WangyiMusicAction = function(action){
this.vender = '網易雲音樂';
this.playingMusic = 'see you again'
}
WangyiMusicAction.prototype = {
last : function() {
this.information = {currentMusic:'Ich will',status:'200|404',message:'上一曲'}
},
next : function() {
this.information = {currentMusic:'一人我編程累',status:'200|404',message:'下一曲'}
},
play : function() {
this.information = {currentMusic:'see you again',status:'200|500',message:'播放'}
},
mute : function() {
this.information = {currentMusic:'see you again',status:'200|500',message:'靜音'}
}
}
var music = new WangyiMusicAction()
music.next(); //執行下一曲動做
console.log('音樂提供商 : '+music.vender);
console.log('正在播放 : '+music.playingMusic);
console.log('執行動做 : ' +music.information.message);
console.log('接口狀態 : ' +music.information.status);
console.log('執行動做後歌曲 : ' +music.information.currentMusic);
音樂提供商 : 網易雲音樂
正在播放 : see you again
執行動做 : 下一曲
接口狀態 : 200|400
----------執行結果--------
執行動做後歌曲 : 一人我編程累
複製代碼
這樣就算是面向對象
的了,雖然達到目的,可是上面所說的,可是這算是Music
的網易雲音樂實現版本、總不能再來一個QQMusic
、XiaMiMusic
吧?咱們創建一個Factory
工廠來管理全部的音樂:this
var WangyiMusicAction = function(action){
this.vender = '網易雲音樂';
this.playingMusic = 'see you again'
}
//爲網易音樂提供共有方法
WangyiMusicAction.prototype = {
last : function() {
this.information = {currentMusic:'Ich will',status:'200|404',message:'上一曲'}
},
next : function() {
this.information = {currentMusic:'一人我編程累',status:'200|404',message:'下一曲'}
},
play : function() {
this.information = {currentMusic:'see you again',status:'200|500',message:'播放'}
},
mute : function() {
this.information = {currentMusic:'see you again',status:'200|500',message:'靜音'}
}
}
var QQMusicAction = function(action){
this.vender = 'QQ音樂';
this.playingMusic = '其實我不low'
}
//爲QQ音樂提供共有方法
QQMusicAction.prototype = {
last : function() {
this.information = {currentMusic:'Ich will',status:'200|404',message:'上一曲'}
},
next : function() {
this.information = {currentMusic:'網易才low',status:'200|404',message:'下一曲'}
},
play : function() {
this.information = {currentMusic:'see you again',status:'200|500',message:'播放'}
},
mute : function() {
this.information = {currentMusic:'see you again',status:'200|500',message:'靜音'}
}
}
//音樂工廠
var MusicFactory = function(type){
switch (type){
case 'qq':
return new QQMusicAction();
case 'wangyi':
return new WangyiMusicAction()
}
}
var music = new MusicFactory('qq')
music.next(); //執行下一曲動做
console.log('音樂提供商 : '+music.vender);
console.log('正在播放 : '+music.playingMusic);
console.log('執行動做 : ' +music.information.message);
console.log('接口狀態 : ' +music.information.status);
console.log('執行動做後歌曲 : ' +music.information.currentMusic);
----------執行結果--------
音樂提供商 : QQ音樂
正在播放 : 其實我不low
執行動做 : 下一曲
接口狀態 : 200|404
執行動做後歌曲 : 網易才low
複製代碼
這樣調用者須要用音樂接口,只須要記住MusicFactory
就能夠了,MusicFactory
就像一個大工廠,對於music
能夠返回他要的一切。spa
好,咱們回過頭來看一下:prototype
第一種方法
:是建立一個新的對象 o 對他來加強 屬性 的功能來實現的. 第二種方法
:是實例化對象來建立的。 第二種方法
:若是他們繼承同一個父類 BaseMusic
那麼他們父類的原型方法是能夠和它們公用的! 第一種方法
:咱們內部 new 了一個新的個體,就不能與父類共用了.
具體哪一種仍是看你需求的,不過我更傾向第二種,由於他擴展性高,需求多的時候咱們甚至能夠將通用的抽離出來放到父類BaseMusic中。
在下面的繼承中我運用了類式繼承
ps:(你們能夠看看構造函數繼承和組合繼承連接在最下面)
複製代碼
//基類(父類)music方法
var BaseMusic = function(){
this.playingMusic = 'see you again'
}
//實現通用方法
BaseMusic.prototype = {
last : function() {
this.information = {status:'200|404',message:'上一曲'}
},
next : function() {
this.information = {currentMusic:'一人我編程累',status:'200|404',message:'下一曲'}
},
play : function() {
this.information = {currentMusic:'see you again',status:'200|500',message:'播放'}
},
mute : function() {
this.information = {currentMusic:'see you again',status:'200|500',message:'靜音'}
}
}
//網易雲的不一樣於父類的構造方法
var WangyiMusicAction = function(action){
this.vender = '網易雲音樂';
}
//這裏經過prototype實現類繼承
WangyiMusicAction.prototype = new BaseMusic();//這些動做我都放在基類了,達到代碼複用的目的
//QQ
var QQMusicAction = function(action){
this.vender = 'QQ音樂';
this.playingMusic = '其實我不low'
}
QQMusicAction.prototype = new BaseMusic() //這些動做我都放在基類了,達到代碼複用的目的
//音樂工廠
var MusicFactory = function(type){
switch (type){
case 'qq':
return new QQMusicAction();
case 'wangyi':
return new WangyiMusicAction()
}
}
var music = new MusicFactory('wangyi')
music.next(); //執行下一曲動做
console.log('音樂提供商 : '+music.vender);
console.log('正在播放 : '+music.playingMusic);
console.log('執行動做 : ' +music.information.message);
console.log('接口狀態 : ' +music.information.status);
console.log('執行動做後歌曲 : ' +music.information.currentMusic);
----------執行結果--------
音樂提供商 : 網易雲音樂
正在播放 : see you again
執行動做 : 下一曲
接口狀態 : 200|404
執行動做後歌曲 : 一人我編程累
複製代碼
這樣看起來是否是更好、更簡潔呢?
解耦
,算是工廠的一種拆解、拼接。我能夠將你的需求分解多個對象建立,更關心的是建立對象的過程。不復雜不能突顯出他的魅力,舉個稍微複雜栗子:
咱們公司是賣車的,用戶下單要買車,這個車呢:
品牌:邁巴赫、林肯、賓利、特斯拉[若是不選品牌,默認特斯拉]
顏色:赤橙黃綠青藍紫...[若是不選顏色,默認黃色]
動力:燃油、電力、混合動力[若是不選動力,默認電力]
購買人的一些備註信息[購買人可能會修改備註須要提供方法]
針對購買人選擇的車型返回對車型的簡單描述[描述能夠修改]
複製代碼
最終根據用戶選擇來生成一個訂單: 想下這用工廠模式是否是要寫不少的if else來返回這麼一個Car的對象呢?
咱們先將 車
購買人的動做
反饋
分解爲三個對象再在最後進行拼接 :
//建立一個汽車
var Car = function(param){
this.color = param && param.color || 'yellow';
this.brand = param && param.brand || 'Tesla';
this.power = param && param.power || 'electric';
}
//提供原型方法
Car.prototype = {
getColor : function () {
return this.color;
},
getBrand : function () {
return this.brand;
},
getPower : function () {
return this.power;
}
}
//建立一個反饋
var FeedBack = function(brand){
var that = this;
(function(brand,that){
switch (brand){
case 'Tesla':
// that.brand = brand;
that.information = '特斯拉是好車'
break
case 'Rolls' :
that.information = '勞斯來時是好車'
}
})(brand,that)
}
FeedBack.prototype.changeBrand = function (information) {
this.information = information;
}
//建立一個顧客
var Client = function(name,message){
this.name = name;
this.message = message || '無留言';
}
//顧客修改備註
Client.prototype.changeMessage = function(message){
this.message = message;
}
//而後重點在這裏!咱們在這裏將咱們分解的拼接起來。
var Order = function(name){
var object = new Car();
object.client = new Client(name);
object.feedBack = new FeedBack(object.brand);
return object;
}
var orderCar = new Order('Vendar-MH');
console.log('The' + orderCar.client.name + '先生、下單一輛' + orderCar.color + '的' + orderCar.brand +' 留言內容 : ' +orderCar.client.message );
orderCar.client.changeMessage('請立刻電話聯繫我')
console.log('The' + orderCar.client.name + '先生、下單一輛' + orderCar.color + '的' + orderCar.brand +' 留言內容 : ' +orderCar.client.message );
----------執行結果--------
TheVendar-MH先生、下單一輛yellow的Tesla 留言內容 : 無留言
TheVendar-MH先生、下單一輛yellow的Tesla 留言內容 : 請立刻電話聯繫我
複製代碼
好了,就算是關於這個訂單的更加複雜的需求,或者修改需求,無論咱們多少各功能在用,咱們只要微微一笑,修改下prototype
等實現就行了0.0
若是您以爲還算不錯能夠關注我持續看個人文章,大概方向:先後端語言設計模式
、如何設計好一款框架
、源碼導讀
、技術實踐
。
147255248