欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

小議javascript 設(shè)計(jì)模式 推薦

 更新時(shí)間:2009年10月28日 14:57:39   作者:  
最近重新溫習(xí)了一次《javascript設(shè)計(jì)模式》,確實(shí)是一本好書,每次看都有不同的領(lǐng)悟,每次領(lǐng)悟到的都受益匪淺,無怪古圣人都說學(xué)無止鏡了,僅以“加油,好嗎?”共勉!
記得早前就說過要和大家分享“javascript設(shè)計(jì)模式”,遲遲沒寫不是因?yàn)槲覒校罱_實(shí)太忙,忙工作,忙旅游(啊哦?),好不容易這幾天空閑了,接下來是兌現(xiàn)之前空口白話的時(shí)間了。
在討論設(shè)計(jì)模式之前,請確認(rèn)您已經(jīng)有一定的腳本編程基礎(chǔ),如果不甚了解,建議可以先查閱本人很久之前寫的這篇《淺談javascript面向?qū)ο缶幊獭氛埧聪乱黄恼隆?
講到設(shè)計(jì)模式,不得不先重點(diǎn)著墨于“接口設(shè)計(jì)”,因?yàn)榻涌谠O(shè)計(jì)在設(shè)計(jì)模式中的意義太大了,大于模式本身。直觀起見,先介紹一下接口定義的形式:
復(fù)制代碼 代碼如下:

var interface = new Interface("interface",[["getName",1],["getAge",1]]);

可以看出接口函數(shù)必須包含兩個(gè)參數(shù),接口方法定義在一個(gè)二維數(shù)組中。上例中定義了兩個(gè)接口方法:getName,getAge,這兩個(gè)方法都帶一個(gè)參數(shù),下面我們詳細(xì)看一下Interface函數(shù)的實(shí)現(xiàn)代碼,從而加深大家對接口的理解。
復(fù)制代碼 代碼如下:

function Interface(name,methods){
if(arguments.length !=2){
console.log("參數(shù)必須為二個(gè)");
}
this.name = name;
this.methods = [];
if(methods.length<1){
console.log("第二個(gè)參數(shù)不能為空數(shù)組");
}
for(var i=0;len=methods.length,i<len;i++){
if(typeof methods[i][0] !== 'string'){
console.log("第一個(gè)參數(shù)數(shù)據(jù)類型必須為字符串");
}
if(methods[i][1] && typeof methods[i][1] !== 'number'){
console.log("第二個(gè)參數(shù)數(shù)據(jù)類型必須為整數(shù)型");
}
if(methods[i].length == 1){
methods[i][1] = 0;
}
this.methods.push(methods[i]);
}
}

從代碼中不難看出,接口函數(shù)的定義規(guī)則:[1]Interface函數(shù)只能包含兩個(gè)參數(shù),第一個(gè)參數(shù)為接口名稱,第二個(gè)參數(shù)是一個(gè)二維數(shù)組[2]第二個(gè)參數(shù)不允許為空數(shù)組[3]methods參數(shù)中的第一個(gè)參數(shù)必須為字符串類型,用以定義方法名,第二個(gè)參數(shù)必須為整數(shù)類型,用以定義方法的參數(shù)個(gè)數(shù)[4]當(dāng)methods中方法的參數(shù)個(gè)數(shù)為0時(shí),可以省略不寫。
接下來要建一個(gè)類,讓該類繼承前面定義的interface接口,那該怎么做呢,別急,我們需要新增一個(gè)方法,見如下代碼:
復(fù)制代碼 代碼如下:

var ioldfish = function(name,age){
this.name = name;
this.age = age;
Interface.regImplement(this,interface);
}
ioldfish.prototype.getName = function(){
alert(this.name);
};
ioldfish.prototype.getAge = function(){
alert(this.age);
};
var fishwl = new ioldfish("老魚",27);
fishwl.getName();

Interface.regImplement就是我們要新增的方法,作用就是讓ioldfish類按照接口interface的規(guī)范編碼,否則將會(huì)在firebug的控制臺拋出異常。
看看這個(gè)方法的具體實(shí)現(xiàn)代碼:
復(fù)制代碼 代碼如下:

Interface.regImplement = function(object){
if(arguments.length<2){
console.log("接口繼承參數(shù)不能少于二個(gè)");
}
for(var i=1;len = arguments.length,i<len;i++){
var interface = arguments[i];
if(interface.constructor !== Interface){
console.log("第三個(gè)參數(shù)開始必須為接口實(shí)例");
}
for(var j=0;len=interface.methods.length,j<len;j++){
var method = interface.methods[j][0];
if(!object[method] || typeof object[method] !=="function" || object[method].getParameters().length !== interface.methods[j][1]){
console.log(""+method+"方法接口不匹配");
}
}
}
}

解讀這段代碼,你很容易發(fā)現(xiàn):[1]Interface.regImplement繼承接口函數(shù)的參數(shù)至少要有兩個(gè),如果有第三個(gè)參數(shù),那么該參數(shù)必須是Interface接口的實(shí)例[2]我們?nèi)ケ闅vinterface接口中的方法,再與新增類中的方法一一匹配,如果發(fā)現(xiàn)繼承了該接口規(guī)范的類缺少某方法,就會(huì)拋出錯(cuò)誤提示。[3]接口對于參數(shù)個(gè)數(shù)也進(jìn)行了匹配,如果接口方法中的參數(shù)個(gè)數(shù)與新增類中方法的個(gè)數(shù)不匹配也會(huì)拋出錯(cuò)誤提示。
為了匹配方法中參數(shù)個(gè)數(shù),這里用到一個(gè)getParameters()方法,我們基于Function做個(gè)擴(kuò)展,代碼實(shí)現(xiàn)如下:
復(fù)制代碼 代碼如下:

Function.prototype.getParameters = function(){
var str = this.toString();
var paramStr = str.slice(str.indexOf("(")+1,str.indexOf(")")).replace(/\s*/g,'');
try{
return (paramStr.length ==0 ? [] : paramStr.split(","));
}
catch(err){
console.log("非法函數(shù)");
}
}

接下來,你可以把所講的Interface函數(shù),Interface.regImplement函數(shù),還有Function.prototype.getParameters函數(shù)整合到一個(gè)interface.js的文件中,調(diào)試一下新建的這個(gè)ioldfish類??纯串?dāng)類中缺少getAge方法時(shí)會(huì)怎么樣?建議新手,各類情況都模擬一下,加強(qiáng)理解吧!如果你確信已經(jīng)完全理解接口設(shè)計(jì),那就跟著我繼續(xù)往下走。
Javascript設(shè)計(jì)模式之單體模式Singleton
單體模式Singleton:這是最基礎(chǔ)的設(shè)計(jì)模式,嚴(yán)格來說沒什么模式可言,但是卻很容易用也很好用,支付寶很多組件都是通過單體模式設(shè)計(jì)的。事實(shí)上在《淺談javascript面向?qū)ο缶幊獭分嘘U述原型繼承的時(shí)候就已經(jīng)用到了該模式,這里簡單帶過,重點(diǎn)說一下惰性單體,這對一些不是所有用戶都需要,在特定情景下才會(huì)用到的組件有非常好的優(yōu)化作用,他可以讓組件的實(shí)例化推遲到用戶觸發(fā)他的時(shí)候。
復(fù)制代碼 代碼如下:

var ioldfish = {
name:'老魚',
age:27,
getName:function(){
alert(name);
},
getAge:function(){
alert(age);
}
}

上例是一個(gè)最簡單的單體模式,把本人的資料都整合到ioldfish這個(gè)對象字面量中,形成一個(gè)模塊,同時(shí)起到了一個(gè)命名空間的作用。
復(fù)制代碼 代碼如下:

var ioldfish =(function(){
var name = '老魚';
var age = 27;
return{
getName:function(){
alert(name);
},
getAge:function(){
alert(age);
}
}
})();

對第一個(gè)單體做簡單的修改,通過閉包讓name,age成為靜態(tài)私有變量,確保實(shí)例化的時(shí)候在內(nèi)存中始終只有一份,這樣更符合單體模式的定義。
下面重點(diǎn)介紹一下惰性單體,廢話少說,先看看我們該如何來實(shí)現(xiàn)惰性單體:
復(fù)制代碼 代碼如下:

var ioldfish = (function(){
var uniqueInstance;
var name = '老魚';
var age = 27;
function constructor(){
return{
getName:function(){
alert(name);
},
getAge:function(){
alert(age);
}
}
}
return{
isInstance:function(){
if(uniqueInstance == null){
uniqueInstance = constructor();
}
return uniqueInstance;
}
}
})();
ioldfish.isInstance().getName();

上面的結(jié)構(gòu)公私分明一目了然,私有變量uniqueInstance(標(biāo)識類是否已經(jīng)實(shí)例化)和私有方法constructor,返回一個(gè)公有方法isInstance(通過該方法可以調(diào)用私有方法constructor中定義的方法),形如:ioldfish.isInstance().getName();先通過isInstance()方法判斷其是否被實(shí)例化,然后通過getName()方法獲取到閉包內(nèi)的私有變量name。該模式的應(yīng)用場景還是很多的,是不是遇見過頁面中需要加載很大的一個(gè)日歷控件,但并非所有用戶都用的到呢?是不是…
Javascript設(shè)計(jì)模式之工廠模式Factory
工廠模式Factory:先創(chuàng)建一個(gè)抽象類,然后基于這個(gè)抽象類派生出子類,并在子類中創(chuàng)建工廠方法,從而把實(shí)例化推遲到對應(yīng)的子類中進(jìn)行,說實(shí)話,工廠模式在javascript中的應(yīng)用有些牽強(qiáng),畢竟javascript不像java存在硬編碼帶來的困攪,要學(xué)習(xí)的只是模式的思想,切忌因?yàn)槟J蕉J健?
不妨舉個(gè)偏激點(diǎn)的例子,為tab切換、下拉列表等組件添加定位,漸隱,延遲等效果,我們可以先為這些組件定義一個(gè)接口:
  var Iwidget = new Interface("iwidget",[["addEffect"]]);
定義該接口,以便之后派生的子類繼承,接口中定義了一個(gè)addEffect方法,接口方法實(shí)現(xiàn)后,調(diào)用的同學(xué)大可不必關(guān)注各子類中對于addEffect方法的代碼實(shí)現(xiàn)。
復(fù)制代碼 代碼如下:

var Widget = function(){};
Widget.prototype={
fire:function(model){
var widget = this.createWidget(model);
//有同學(xué)問為什么子類都必須定義接口方法,因?yàn)橄旅嬉{(diào)用嘛
widget.addEffect();
return widget;
},
show:function(){
//show代碼具體實(shí)現(xiàn)
},
hide:function(){
//hide代碼具體實(shí)現(xiàn)
},
createWidget:function(model){
alert('抽象類,不可以實(shí)例化')
}
};

上例先定義一個(gè)抽象類Widget,做為派生子類的父類,由于考慮到這兩類組件都涉及到隱藏和顯示一個(gè)容器,所以在父類中預(yù)先定義好show和hide方法以便子類繼承。
復(fù)制代碼 代碼如下:

var xTab = function(){};
extend(xTab,Widget);
xTab.prototype.createWidget = function(model){
var widget;
switch(model){
case 'position':
widget = new xTabPosition();
break;
case 'anim':
widget = new xTabAnim();
break;
case 'delay':
default:
widget = new xTabDelay();
}
};
var dropDown = function(){};
extend(dropDown,Widget);
dropDown.prototype.createWidget = function(model){
var widget;
switch(model){
case 'position':
widget = new dropDownPosition();
break;
case 'anim':
widget = new dropDownAnim();
break;
case 'delay':
default:
widget = new dropDownDelay();
}
};

子類xTab和dropDown繼承了父類,并且重寫了createWidget方法,不同的子類根據(jù)定位,漸隱,延遲效果分別創(chuàng)建不同的實(shí)例,只要?jiǎng)?chuàng)建這些實(shí)例的類都實(shí)現(xiàn)接口中約定的addEffect方法,至于方法代碼如何實(shí)現(xiàn),千篇一律,愛咋整咋整。
復(fù)制代碼 代碼如下:

var xTabPosition = function(){};
xTabPosition.prototype ={
addEffect:function(){
//具體實(shí)現(xiàn)代碼
}
};
var dropDownPosition = function(){};
dropDownPosition.prototype ={
addEffect:function(){
//具體實(shí)現(xiàn)代碼
}
};
var dropDownInstance = new dropDown();
dropDownInstance.fire('position');

以此類推,如果您需要為氣泡組件添加這些效果,照葫蘆畫瓢就可以了,說到這里你可以清楚的看到,這種設(shè)計(jì)模式大大降低了類和類之間的耦合度,而且可以根據(jù)具體的交互需求,實(shí)現(xiàn)不同的輔助動(dòng)作,但是也無可避免的增加了代碼實(shí)現(xiàn)上的復(fù)雜性,事實(shí)上這種模式并不適合javascript,畢竟它有別于java,不會(huì)有類名硬編碼的問題,目的是學(xué)習(xí)他的設(shè)計(jì)思想,所以以上示例僅供參考,如無大人在旁,小朋友切勿效仿。
對于javascript愛好者來說,更有價(jià)值的應(yīng)該是工廠模式中講到的的”緩存(memoization)機(jī)制”,書上舉了個(gè)創(chuàng)建XHR對象的例子來說明該特性,但是效果顯然不夠明顯……
memoization名詞解釋:把函數(shù)的每次執(zhí)行結(jié)果都放入一個(gè)鍵值對(數(shù)組也可以,視情況而定)中,在接下來的執(zhí)行中,在鍵值對中查找是否已經(jīng)有相應(yīng)執(zhí)行過的值,如果有,直接返回該值,沒有才 真正執(zhí)行函數(shù)體的求值部分。很明顯,找值,尤其是在鍵值對中找值,比執(zhí)行函數(shù)快多了
在遞歸調(diào)用的時(shí)候,memoization的威力才能更好的顯現(xiàn)。下面是一個(gè)經(jīng)典的斐波納契序列,fib(20) 會(huì)把fib這個(gè)方法執(zhí)行21891次,如果是fib(40),這會(huì)執(zhí)行331160281次。
復(fù)制代碼 代碼如下:

function fib(n) {
if (n < 2) {
return n;
}
return fib(n - 1) + fib(n - 2);
}

再看看如何使用memoization來實(shí)現(xiàn):
復(fù)制代碼 代碼如下:

var iterMemoFib = (function() {
var cache = [1, 1];
var fib = function(n) {
if (n >= cache.length) {
//將一個(gè)遞歸轉(zhuǎn)換成了一個(gè)
for (var i = cache.length; i <= n; i++) {
cache[i] = cache[i - 2] + cache[i - 1];
}
}
return cache[n-1];
}
return fib;
})();

將Function的原型擴(kuò)展memoize 和unmemoize 方法,這樣你可以對任何函數(shù)實(shí)現(xiàn)memoize和解除memoize,當(dāng)然,這個(gè)方法要慎,對一些不是頻繁執(zhí)行的函數(shù),沒必要緩存:
復(fù)制代碼 代碼如下:

Function.prototype.memoize = function() {
var pad = {};
var self = this;
var obj = arguments.length > 0 ? arguments[i] : null;
var memoizedFn = function() {
// 把參數(shù)作為數(shù)組保存,作為鍵,把函數(shù)執(zhí)行的結(jié)果作為值緩存起來
var args = [];
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
if (!(args in pad)) {
pad[args] = self.apply(obj, arguments);
}
return pad[args];
}
memoizedFn.unmemoize = function() {
return self;
}
return memoizedFn;
}
Function.prototype.unmemoize = function() {
alert("Attempt to unmemoize an unmemoized function.");
return null;
}

使用方法:fib.memoize();
Javascript設(shè)計(jì)模式之組合模式
組合模式:運(yùn)用該設(shè)計(jì)模式可以通過組合對象添加屬性和方法,通過遞歸批量式的讓葉子對象得到組合對象的屬性和方法。打個(gè)比方我們現(xiàn)在要?jiǎng)討B(tài)創(chuàng)建一個(gè)銀行列表,按銀行類型分為網(wǎng)上銀行類,卡通銀行類,并可配置他們是否顯示。用組合模式如何實(shí)現(xiàn)呢?
第一步還是先定義接口,因?yàn)橐龅侥愁愩y行甚至某個(gè)銀行是否顯示可配置,那么我們先約定2個(gè)接口,showBank和hideBank。
var IcardItem = new Interface(”icardItem”,[["showBank"],["hideBank"]]);
接下來先定義卡的組合對象,并設(shè)置組合對象的基本方法add,remove,getChild,由于這個(gè)類繼承了IcardItem接口類,所以還定義了showBank,hideBank這兩個(gè)接口方法。
復(fù)制代碼 代碼如下:

var cardMain = function(id){
this.cards = [];
this.element = document.createElement("div");
this.element.id = id;
Interface.regImplement(this,IcardItem);
};
cardMain.prototype = {
add:function(card){
this.cards.push(card);
this.element.appendChild(card.getElement());
},
remove:function(card){
for(i=0;len=this.cards.length,i<len;i++){
if(cards[i] == card){
this.cards.splice(i,1);
break;
}
this.element.removeChild(card.getElement());
}
},
getChild:function(i){
return this.cards[i];
},
getElement:function(){
return this.element;
},
showBank:function(){
this.element.style.display ="block";
for(i=0;len=this.cards.length,i<len;i++){
this.cards[i].showBank();
}
},
hideBank:function(){
this.element.style.display ="none";
for(i=0;len=this.cards.length,i<len;i++){
this.cards[i].hideBank();
}
}
};

然后定義葉子對象類bankLogo用以創(chuàng)建銀行l(wèi)ogo,這里銀行l(wèi)ogo都以帶class的a標(biāo)簽標(biāo)識:
復(fù)制代碼 代碼如下:

var bankLogo = function(bankClassName){
this.element = document.createElement("a");
this.element.className = bankClassName;
Interface.regImplement(this,IcardItem);
};
bankLogo.prototype ={
showBank:function(){
this.element.style.display ="block";
},
hideBank:function(){
this.element.style.display ="none";
},
getElement:function(){
return this.element;
}
};

最后設(shè)置一個(gè)單體對象,將操作銀行的相關(guān)信息形成一個(gè)模塊,方便調(diào)用:
復(fù)制代碼 代碼如下:

var BankAction ={
bankList:[],
addBank:function(card){
this.bankList.push(card);
},
innerBank:function(conId){
for(i=0;len=this.bankList.length,i<len;i++){
var cardObj =this.bankList[i].getElement();
}
document.getElementById(conId).appendChild(cardObj);
}
};

到了實(shí)現(xiàn)環(huán)節(jié)了,實(shí)例化生成一個(gè)包含所有卡的最外層容器,然后根據(jù)卡類,分別生成一個(gè)放置銀行卡和卡通卡的容器,最后生成各銀行卡的實(shí)例,并按層級關(guān)系形成DOM結(jié)構(gòu):
復(fù)制代碼 代碼如下:

var bankDivT = new cardMain("PayCard");//創(chuàng)建最外層容器
var ebankCard = new cardMain("ebankCard");//創(chuàng)建網(wǎng)銀類銀行卡容器
var ktCard = new cardMain("ktCard");//創(chuàng)建卡通類銀行卡容器
var ccbBank = new bankLogo('Ebank-CMB');//創(chuàng)建招行銀行卡
var abcBank = new bankLogo('Ebank-ABC');//創(chuàng)建農(nóng)行銀行卡
var abcKtBank = new bankLogo('Kt-ABC');//創(chuàng)建卡通農(nóng)行卡
ebankCard.add(ccbBank);
ebankCard.add(abcBank);
ktCard.add(abcKtBank);
bankDivT.add(ebankCard);
bankDivT.add(ktCard);
BankAction.addBank(bankDivT);
BankAction.innerBank("bankList");

將動(dòng)態(tài)生成的銀行列表,DOM結(jié)構(gòu)形如:
復(fù)制代碼 代碼如下:

<div id="PayCard">
<div id="ebankCard">
<a class="Ebank-CMB"></a>
<a class="Ebank-ABC"></a>
</div>
<div id="ktCard">
<a class="Kt-ABC"></a>
</div>
</div>

組合模式應(yīng)用在動(dòng)態(tài)生成用戶界面的時(shí)候,是非常不錯(cuò)的選擇,他可以很大程度的簡化粘合性代碼,提升維護(hù)性。不過還是要慎用,畢竟當(dāng)葉子對象很多的時(shí)候,遞歸還是存在性能上的問題。
Javascript設(shè)計(jì)模式之裝飾者模式
裝飾者模式:可以不創(chuàng)建新的子類,給對象創(chuàng)建新的功能。舉例說明:支付寶收銀臺紅包結(jié)合余額付款的應(yīng)用場景。
   var Ieconomics = new Interface("ieconomics",[["getPrice"]]);
首先創(chuàng)建一個(gè)組件類,基與該組件實(shí)例化的對象,會(huì)被作為參數(shù)傳遞給裝飾者類,以便裝飾者調(diào)用到該組件中的各方法。
復(fù)制代碼 代碼如下:

  var economic = function(){
Interface.regImplement(this,Ieconomics);
};
economic.prototype={
getPrice:function(){
//代碼實(shí)現(xiàn)
}
};

然后創(chuàng)建一個(gè)裝飾者抽象類,作為派生裝飾者選件類的父類:
復(fù)制代碼 代碼如下:

  var economicsDecorator = function(economic){
this.economic = economic;
this.regImplement(economic,Ieconomics);
};
economicsDecorator.prototype={
getPrice:function(){
return this.economic.getPrice();
}
};

最后基于上面這個(gè)抽象類,派生出一個(gè)裝飾者選件類:
復(fù)制代碼 代碼如下:

  //紅包裝飾者選件類
var coupon = function(economic){
//調(diào)用裝飾著抽象類的構(gòu)造函數(shù)
economicsDecorator.call(this,economic);
};
extend(coupon,couponDecorator);
coupon.prototype=function(){
//改寫getPrice方法
getPrice:function(){
return this.economic.getPrice() - this.getCoupon();
},
getCoupon:function(){
//獲取紅包總價(jià)具體實(shí)現(xiàn)
}
};
var myCoupon = new economic();
myCoupon = new coupon(myCoupon);

實(shí)現(xiàn)裝飾者模式就是這么簡單,首先創(chuàng)建一個(gè)組件的實(shí)例myCoupon,然后將該對象作為參數(shù)傳遞給裝飾者選件類coupon。你會(huì)發(fā)現(xiàn)兩句代碼中我都把值賦給了變量myCoupon,這是因?yàn)樗麄兌紝?shí)現(xiàn)了同一個(gè)接口類,他們之間是可以互換使用的。
看到這里心細(xì)的同學(xué)可能會(huì)發(fā)現(xiàn),我們在coupon類中新增了一個(gè)getCoupon方法,目前來看不會(huì)有任何問題,但是如果我們繼續(xù)創(chuàng)建一個(gè)購物卷裝飾者選件類,然后結(jié)合紅包一起用呢?
復(fù)制代碼 代碼如下:

//購物卷裝飾者選件類
var voucher = function(economic){
economicsDecorator.call(this,economic);
};
extend(voucher,couponDecorator);
voucher.prototype=function(){
getPrice:function(){
return this.getPrice() - this.getVoucher();
},
getVoucher:function(){
//獲取優(yōu)惠卷總價(jià)具體實(shí)現(xiàn)
}
};
var myCoupon = new economic();
myCoupon = new coupon(myCoupon);
myCoupon = new voucher(myCoupon);

在這種場景下面getCoupon方法已經(jīng)找不到了,這是因?yàn)関oucher裝飾myCoupon的時(shí)候,它的父類economicsDecorator不包含getCoupon方法,那自然是取不到的了,那該怎么辦呢?
分析一下裝飾者抽象類economicsDecorator,我們傳遞了一個(gè)myCoupon的引用作為參數(shù),我們可以通過這個(gè)參數(shù)做一些小動(dòng)作,獲得新增加的方法。
 
復(fù)制代碼 代碼如下:

 var economicsDecorator = function(economic){
this.economic = economic;
this.interface = Ieconomics;
for(var k in this.economic){
if(typeof this.economic[key] !== "function"){
continue;
var i;
for(i = 0;len = this.interface.methods.length,i < len; i++) {
//通過遍歷比較在接口類中是否包含此方法,如果包含返回下一個(gè)
if(key == this.interface.methods[i][0]) {
break;
}
}
if(i < this.interface.methods.length)
continue;
var decorator = this;
//采用匿名函數(shù)調(diào)用方式來定義新方法
(function(methodName) {
decorator[methodName] = function() {
return decorator.economic[methodName]();
};
})(key);
}
}
}
this.regImplement(economic,Ieconomics);
};
economicsDecorator.prototype={
getPrice:function(){
return this.economic.getPrice();
}
};

看上面的代碼,我們對裝飾者抽象類做了一些修改,這樣做是為了確保在裝飾者選件類中一旦定義新方法,可以在裝飾者抽象類中動(dòng)態(tài)的定義出來。這里只是提供一個(gè)使用裝飾者模式的思路,具體的實(shí)現(xiàn)代碼遠(yuǎn)比這個(gè)復(fù)雜,由于項(xiàng)目還在開發(fā)中,demo暫不提供,支付寶新版收銀臺發(fā)布后,會(huì)跟大家再做個(gè)詳細(xì)的設(shè)計(jì)分享。
Javascript設(shè)計(jì)模式之橋接模式
橋接模式:將抽象和其實(shí)現(xiàn)分離開來,以便二者獨(dú)立變化。其實(shí)很簡單,只是在API和具體事件之間增加一個(gè)橋梁,從而降低API和使用他的類和對象之間的耦合。
事實(shí)上對大多數(shù)同學(xué)來說橋接模式并不陌生,下面的this.getName就是一種橋接方法,他是外訪問的一個(gè)接口,他的內(nèi)部實(shí)現(xiàn)是通過訪問內(nèi)部私有變量來實(shí)現(xiàn)的,這個(gè)方法起到了外部和內(nèi)部溝通的橋梁作用。
復(fù)制代碼 代碼如下:

var ioldfish = function(){
var name = '老魚';
this.getName = function(){
alert(name);
}
}

橋接模式用的最多的還是在事件監(jiān)聽器回調(diào)函數(shù)。下面這個(gè)是獲取用戶信息的API接口函數(shù):
復(fù)制代碼 代碼如下:

function getUserInfo(userid,callback){
asyncRequest('GET','userInfo?userid='+userid,function(resp){
callback(resp.responseText);
});
}

接下去我們要做的是把這個(gè)API和某個(gè)事件的觸發(fā)建立一個(gè)橋梁關(guān)系
addEvent(element,'click',bridgeMethod);
function bridgeMethod(e){
getUserInfo(this.userid,function(){
//回調(diào)函數(shù)實(shí)現(xiàn)代碼
});
}
這里在element對象click的時(shí)候觸發(fā)函數(shù)并不是getIserInfo,而是新建了一個(gè)橋接方法bridgeMethod,通過這層橋接使得API接口函數(shù)和click事件相對獨(dú)立,這樣大大拓寬了API的適用范圍。
Javascript設(shè)計(jì)模式之適配器模式
適配器模式:打個(gè)比方,你維護(hù)了一個(gè)系統(tǒng),之前一直都是用prototype框架,但是現(xiàn)在打算新引入YUI框架,那如何讓兩個(gè)框架平穩(wěn)過度呢
,舉個(gè)例子,如何將prototype中的$方法轉(zhuǎn)換為YUI中的get方法:
復(fù)制代碼 代碼如下:

function $(){};
function YAHOO.util.Dom.get=function(el){};
function prototypeToYuiAdapter(){
return YAHOO.util.Dom.get(arguments);
}

你要在prototype中使用yui的get方法,只需要做以下申明即可:
   $ = prototypeToYuiAdapter;
這樣的話,在prototype中就可以使用YUI中的get方法了。本人并不是很推崇這種模式,所以不多做闡述,事實(shí)上我覺得不到萬不得以,我們根本不需要使用這種模式,作為一名負(fù)責(zé)任的設(shè)計(jì)者,我寧可做代碼重構(gòu)也不希望使用該模式,只能作為無奈之下的過渡型方案使用。
Javascript設(shè)計(jì)模式之門面模式,觀察者模式
門面模式:這應(yīng)該是所有腳本框架中都用到的,最基礎(chǔ)的設(shè)計(jì)模式,隨便找個(gè)框架中定義好的方法看看就行了,比如說YUI中的setStyle方法等等等等。在這里就不多闡述了。
觀察者模式:該設(shè)計(jì)模式應(yīng)用在javascript上似乎更為牽強(qiáng),不甚理解,這里就不說了,以免誤人子第,如有心得者不吝賜教。
一天時(shí)間都耗在這篇博文上了,好象還有很多想寫的,看來要把心里想的東西寫清楚還是不容易的,再整理整理再說吧,敬請期待!

相關(guān)文章

  • 基于Bootstrap 3 JQuery及RegExp的表單驗(yàn)證功能

    基于Bootstrap 3 JQuery及RegExp的表單驗(yàn)證功能

    這篇文章主要介紹了基于Bootstrap 3 JQuery及RegExp的表單驗(yàn)證功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-02-02
  • 一文詳解Proxy和Object.defineProperty的使用與區(qū)別

    一文詳解Proxy和Object.defineProperty的使用與區(qū)別

    在JavaScript中,對象是一種核心的數(shù)據(jù)結(jié)構(gòu),而對對象的操作也是開發(fā)中經(jīng)常遇到的任務(wù),本文將深入比較Proxy和Object.defineProperty,感興趣的小伙伴可以了解下
    2023-12-12
  • ckeditor一鍵排版功能實(shí)現(xiàn)方法分析

    ckeditor一鍵排版功能實(shí)現(xiàn)方法分析

    這篇文章主要介紹了ckeditor一鍵排版功能實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了ckeditor一鍵排版相關(guān)擴(kuò)展插件定義、配置與使用方法,需要的朋友可以參考下
    2020-02-02
  • layui+ssm實(shí)現(xiàn)數(shù)據(jù)批量刪除功能

    layui+ssm實(shí)現(xiàn)數(shù)據(jù)批量刪除功能

    本篇文章給大家介紹layui+ssm實(shí)現(xiàn)數(shù)據(jù)批量刪除功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-12-12
  • JavaScript簡單實(shí)現(xiàn)彈出拖拽窗口(一)

    JavaScript簡單實(shí)現(xiàn)彈出拖拽窗口(一)

    這篇文章主要為大家詳細(xì)介紹了JavaScript簡單實(shí)現(xiàn)彈出拖拽窗口的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-06-06
  • JS實(shí)現(xiàn)無縫循環(huán)marquee滾動(dòng)效果

    JS實(shí)現(xiàn)無縫循環(huán)marquee滾動(dòng)效果

    這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)無縫循環(huán)marquee滾動(dòng)效果,兼容IE, FireFox, Chrome,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • BootStrap注意事項(xiàng)小結(jié)(五)表單

    BootStrap注意事項(xiàng)小結(jié)(五)表單

    這篇文章主要介紹了BootStrap注意事項(xiàng)小結(jié)(五)表單的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,,需要的朋友可以參考下
    2017-03-03
  • JS對象與json字符串格式轉(zhuǎn)換實(shí)例

    JS對象與json字符串格式轉(zhuǎn)換實(shí)例

    這篇文章主要介紹了JS對象與json字符串格式轉(zhuǎn)換方法,以實(shí)例的形式詳細(xì)講述了js對象與json字符串格式轉(zhuǎn)換的技巧,需要的朋友可以參考下
    2014-10-10
  • JavaScript中 ES6 generator數(shù)據(jù)類型詳解

    JavaScript中 ES6 generator數(shù)據(jù)類型詳解

    generator 是ES6引入的新的數(shù)據(jù)類型,由function* 定義, (注意*號),接下來通過本文給大家介紹js中 ES6 generator數(shù)據(jù)類型,非常不錯(cuò),感興趣的朋友一起學(xué)習(xí)吧
    2016-08-08
  • JS中hasOwnProperty方法用法簡介

    JS中hasOwnProperty方法用法簡介

    hasOwnProperty(propertyName)方法 是用來檢測屬性是否為對象的自有屬性,如果是,返回true,否者false; 參數(shù)propertyName指要檢測的屬性名,這篇文章給大家介紹JS中hasOwnProperty方法用法簡介,感興趣的朋友一起看看吧
    2024-01-01

最新評論