![JavaScript設(shè)計模式之策略模式_第1頁](http://file2.renrendoc.com/fileroot_temp3/2021-3/27/a9413379-9d42-4703-a14c-b3d661a416bd/a9413379-9d42-4703-a14c-b3d661a416bd1.gif)
![JavaScript設(shè)計模式之策略模式_第2頁](http://file2.renrendoc.com/fileroot_temp3/2021-3/27/a9413379-9d42-4703-a14c-b3d661a416bd/a9413379-9d42-4703-a14c-b3d661a416bd2.gif)
![JavaScript設(shè)計模式之策略模式_第3頁](http://file2.renrendoc.com/fileroot_temp3/2021-3/27/a9413379-9d42-4703-a14c-b3d661a416bd/a9413379-9d42-4703-a14c-b3d661a416bd3.gif)
![JavaScript設(shè)計模式之策略模式_第4頁](http://file2.renrendoc.com/fileroot_temp3/2021-3/27/a9413379-9d42-4703-a14c-b3d661a416bd/a9413379-9d42-4703-a14c-b3d661a416bd4.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、JavaScript設(shè)計模式之策略模式JavaScript設(shè)計模式之策略模式在網(wǎng)上搜索“為什么MVC不是一種設(shè)計模式呢?”其中有解答:MVC其實是三個經(jīng)典設(shè)計模式的演變:觀察者模式(Observer)、策略模式(Strategy)、組合模式(Composite)。所以我今天選擇學(xué)習策略模式。策略模式:定義了一系列家族算法,并對每一種算法單獨封裝起來,讓算法之間可以相互替換,獨立于使用算法的客戶。通常我并不會記得“牛頓第一定律”的具體內(nèi)容,所以我也難保證我會對這個定義記得多久用FE經(jīng)常見到的東西來舉個例子說明一下:1.$(div).animation(left: 50px,1000,easein
2、);2.3.$(div).animation(left: 50px,1000,linear);4.5.$(div).animation(left: 50px,1000,swing);6.7./看最后三個關(guān)于動畫效果的參數(shù)8.9./Jquery文檔總提到easing(第三個參數(shù)):要使用的擦除效果的名稱(需要插件支持).默認jQuery提供linear 和 swing.我們在對元素設(shè)置動畫的緩動效果,實際就是策略模式的一種實現(xiàn)。這樣的緩動算法跟我們使用Jquery的人來說沒有直接關(guān)系,假如我的項目中某個動畫需要一種新的算法效果,那么我們再去開發(fā)一個插件就好了。反之,如果Jquery沒有提供這樣一
3、種插件機制,那針對需求變化難不成要去改動Jquery 的源碼嗎?在大話設(shè)計模式一書中,作者舉例的是一個商場的收銀系統(tǒng),在實際操作中,商場可能因為“雙11買一送一”、“滿500立減50”、“中秋節(jié)全場 11折”等活動而對最終的收費產(chǎn)生變化。如果哪一天商場突然倒閉,全場兩元,這時候我們僅需要給軟件系統(tǒng)增加一個所有商品價格變兩元的插件算法(類)即可。我先來模擬一下策略模式的基本代碼形態(tài):. 5. . function ConcreteStrategyA()10.this.AlgorithmInterface = function()11. console.log(算法A)
4、;12. 13. 14.15. function ConcreteStrategyB()16.this.AlgorithmInterface = function()17. console.log(算法B);18. 19. 20.21. function ConcreteStrategyC()22.this.AlgorithmInterface = function()23. console.log(算法C);24. 25. 26.27./Context,用一個createStrategy來配置,維護一個對Strategy對象的引用28.29. function Context(strateg
5、y)30.this.strategy = strategy;31.this.ContextInterface = function()32. strategy.AlgorithmInterface();33. 34.35. 36.37./應(yīng)用38. var context1 = new Context(new ConcreteStrategyA();39. context1.ContextInterface();40.41. var context2 = new Context(new ConcreteStrategyB();42. context2.ContextInterface();43
6、.44. var context3 = new Context(new ConcreteStrategyC();45. context3.ContextInterface();46. 47.48.通常來說,具體的某一種算法必須保證實現(xiàn)了某一些接口或者繼承某個抽象類,才不會發(fā)生類型錯誤,在javascript中去實現(xiàn)接口、抽象類、繼承等特性要費一些周章,所以我這個例子是不嚴謹?shù)模瑑H從最簡單的實現(xiàn)方式著手。具體實現(xiàn)一個商場收銀系統(tǒng):包括一個單獨js文件,和一個具體的實現(xiàn)html文件1./因為要用到數(shù)值驗證,所以.這里用的是jquery2.1里面的isNum2.function isNum(obj)
7、3.return obj - parseFloat(obj)=0;4.5./算法A,沒有活動,正常收費6.function ConcreteStrategyA()7.this.AlgorithmInterface = function(money)8.return money;9. 10.11./算法B,滿300減10012.function ConcreteStrategyB(MoneyCondition,MoneyReturn)13.this.MoneyCondition = MoneyCondition,14.this.MoneyReturn = MoneyReturn;15.16.th
8、is.AlgorithmInterface = function(money)17. var result=money;18.if(money=MoneyCondition)19. result = money - Math.floor(money/MoneyCondition)*MoneyReturn;20. 21.return result;22. 23.24./算法C,打折25.function ConcreteStrategyC(moneyRebate)26.this.moneyRebate = moneyRebate;27.this.AlgorithmInterface = func
9、tion(money)28.return money*this.moneyRebate;29. 30.31.32./Context,用一個createStrategy來配置,維護一個對Strategy對象的引用33./這里將算法相關(guān)的從客戶端剝離出來,簡單工廠模式34.function Context(type)35.this.strategy = null;36.switch(type)37.casea:38.this.strategy = new ConcreteStrategyA();39.break;40.caseb:41.this.strategy = new ConcreteStr
10、ategyB(300,100);42.break;43.casec:44.this.strategy = new ConcreteStrategyC(0.8);45.break;46. 47.48.this.ContextInterface = function(money)49.if(!isNum(money)50. money = 0;51. 52.return this.strategy.AlgorithmInterface(money);53. 54.55.HTML部分:.5.6.7. .block 8. padding:5px 0;9. border-bottom:1p
11、x solid #ccc;10. 11. .menu margin:10px auto;text-align: center;5.16.10017.18.19.加一個/6. var tPrice = document.getElementsByClassName(tPrice),27.tNum = document.getElementsByClassName(tNum),28.tAlg = document.getElementsByClassName(tAlg),29.tMoney = document.getElementsByC
12、lassName(tMoney),30.total = document.querySelector(#total);31.32. var addBtn = document.querySelector(#addBtn);33. addBtn.addEventListener(click,function()34. var html = abel單價(RMB):10035. var div = document.createElement(div);36.div.className=block;37.div.innerHTML = html;38. this.parentNode.parent
13、Node.insertBefore(div,this.parentNode);39. )40.41.42. function calculate(e)43.44. /根據(jù)事件對象判斷事件源,獲取同類元素中的位置45. var num = 0,className = e.target.className;46. switch(className)47. case tPrice:48. for(var i=tPrice.length-1;i=0;i-)49. if(tPricei=e.target)50.num = i;51. 52. 53. break;54. case tNum:55. for
14、(var i=tNum.length-1;i=0;i-)56. if(tNumi=e.target)57.num = i;58. 59. 60. break;61. case tAlg:62. for(var i=tAlg.length-1;i=0;i-)63. if(tAlgi=e.target)64.num = i;65. 66. 67. break;68. default:69. return;70. 71.72.73. var context = new Context(tAlgnum.value);74. var money = 0;75. var totalValue = 0;76
15、.77.money = context.ContextInterface(tPricenum.value*tNumnum.value);78.79. tMoneynum.value = money;80.81. for(var index=0,len=tMoney.length;index20.21.22. 23.24.25. 26.27./發(fā)布者28. function Publisher(obj)29.this.observers = ;30. var number = 0;31.32.this.getState=function()33.return number;34. 35.this
16、.setState = function(num)36. number = num;37.this.notice();38. 39. 40. Ptotype.addOb=function(observer)41. var flag = false;42.for (var i = this.observers.length - 1;i = 0; i-) 43.if(this.observersi=observer)44. flag=true;45. 46. ;47.if(!flag)48.this.observers.push(observer);49. 50.retur
17、n this;51. 52.53. Ptotype.removeOb=function(observer)54. var observers = this.observers;55.for (var i = 0; i +) 56.if(observersi=observer)57. observers.splice(i,1);58. 59. ;60.return this;61. 62. Ptotype.notice=function()63. var observers = this.observers;64.for (var i = 0; i
18、 +) 65. observersi.update(this.getState();66. ;67. 68.69./訂閱者70. function Subscribe(obj)71.this.obj = obj;72.this.update = function(data)73.this.obj.value = data;74. ;75. 76.77./實際應(yīng)用78. var tPrice = document.getElementsByClassName(tPrice),79. tNum = document.getElementsByClassName(tNum),80. tAlg = d
19、ocument.getElementsByClassName(tAlg);81.82. var pba = new Publisher(document);83.84. var oba = new Subscribe(document.getElementsByClassName(tMoney);85. var obb = new Subscribe(document.querySelector(#total);86.87.88. pba.addOb(oba).addOb(obb);89.90. oba.update = function(num)91. var context = new C
20、ontext(tAlgnum.value);92. var money = 0;93.94. money = context.ContextInterface(tPricenum.value*tNumnum.value);95.96.this.objnum.value = money;97. 98. obb.update = function(num)99. var totalValue = 0,100. tMoney = document.getElement sByClassName(tMoney);101.for(var index=0,len=tMoney.lengt h;index=
21、0;i-)125.if(tPricei=e.targ et)126. num = i;127. 128. 129.break;130.casetNum:131.for(var i=tNum.length-1;i=0;i-)132.if(tNumi=e.target )133. num = i;134. 135. 136.break;137.casetAlg:138.for(var i=tAlg.length-1;i=0;i-)139.if(tAlgi=e.target )140. num = i;141. 142. 143.break;144.default:145.return;146. 1
22、47. pba.setState(num);148. 149.150. document.addEventListener(keyup,ca lculate,false);151. document.addEventListener(change,c alculate,false);152. 153.154.噢NO這尼瑪有哪怕一點優(yōu)雅的樣子嗎?反倒是徒添麻煩。不行,我既然學(xué)了這個,那么接下來就要學(xué)MVC了,MVC真的是長這樣的嗎?于是我又開始了度娘之旅。發(fā)現(xiàn)了這樣一篇文章:JavaScript的MVC模式這篇文章也是譯文,好在我學(xué)過觀察者模式了,耐著性子看吧看著有點暈,這種觀察者模式跟我之前學(xué)
23、的不一樣?。繛榱送耆@篇文章的思路,我拿出筆紙開始畫圖,由于畫工不好,字也寫得差,我就不貼圖了,弄一個對該文章整理思路后的總結(jié):我在之前學(xué)習觀察者模式的時候,僅僅是對DOM元素進行了發(fā)布者與訂閱者的區(qū)分,卻不知道也沒有思考過數(shù)據(jù)、視圖與控制器這種結(jié)構(gòu)中的發(fā)布者與訂閱者區(qū)分,所以還是要多看看不同的案例。學(xué)習完這篇文章以后,我依葫蘆畫瓢對我這個“收銀系統(tǒng)”也弄一下,但是我畢竟還沒有學(xué)“組合模式”,所以我也不打算再寫一個Controller,僅僅是Model和View之間加入觀察者模式。最后的結(jié)果是這樣的:. 5. 6.7. .block 8. padding:5px 0;9. b
24、order-bottom:1px solid #ccc;10. 11. .menu margin:10px auto;text-align: center;12. 6. 10017.18.19. 加一個 /20.21.22. 23.24.25. 26.27./實現(xiàn)了觀察者的Event類28. function Event(pub)29.this._pub = pub;30.this._listener = ;31. 32. Etotype = 33. attach: function(listener)34.this._listener.push(liste
25、ner);35. ,36. notify: function(num)37.for(var i=0;i;i+)38.this._listeneri(this._pub,num);39. 40. 41. 42.43./模型44. function Model(data)45.this._data =new Array();46.this._data.push(data);47.this.itemAdded = new Event(this);48.this.itemChanged = new Event(this);49. 50. Mtotype = 51. itemAdd :
26、function(arr)52.this._data.push(arr);53.this.itemAdded.notify(this._data.length-1);54. ,55. itemChange : function(arr,value)56. var a = arr0, b=arr1;57.this._dataab = value;58.this.itemChanged.notify(a);59. 60.61. 62./視圖63. function View(model,ele)64.this._model = model;65.this._ele = ele;66. var th
27、at = this;67.68./綁定模型偵聽器69.this._model.itemAdded.attach(function(pub,num)70. that.getTotal(pub,num);71. );72.this._model.itemChanged.attach(function(pub,num)73. that.getTotal(pub,num);74. );75.76./綁定DOM偵聽器77.this._ele.eTarget.addEventListener(keyup,function(e)78. var target = e.target,79. className
28、= target.className;80.if(target.nodeName.toLowerCase()!=input)81.return;82. 83. var elements = document.getElementsByClassName(className),84. a,b;85.for(var i=elements.length-1;i=0;i-)86.if(elementsi=target)87. a = i;88. 89. 90.switch(className)91.casetPrice:92. b = 0;93.break;94.casetNum:95. b = 1;
29、96.break;97.casetMoney:98. b = 3;99.break;100. 101.if(!isNum(a)102. a = 0;103. 104.if(!isNum(b)105. b = 0;106. 107. that._model.itemChange(a,b ,target.value);108. );109.this._ele.eTarget.addEventListen er(change,function(e)110. var target = e.target,111. className = target.class Name;112.if(target.n
30、odeName.toLowerCa se()!=select)113.return;114. 115. var elements = document.getE lementsByClassName(className),116. a;117.for(var i=elements.length-1;i=0;i-)118.if(elementsi=target) 119. a = i;120. 121. 122. that._model.itemChange(a,2 ,target.value);123. );124.this._ele.addBtn.addEventListene r(clic
31、k,function()125. var html = product100打8折126. var div = document.createEle ment(div);127. div.className=block;128. div.innerHTML = html;129.this.parentNode.parentNode.i nsertBefore(div,this.parentNode);130.131. that._model.itemAdd(0,0,a,0);132. );133. 134. Vtotype.getTotal= function(pu b,num)135. var price = this._model._datan
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度新能源汽車充電樁設(shè)備采購合同協(xié)議書
- 2024婦女節(jié)活動中班(6篇)
- 2025年江西省高三語文2月統(tǒng)一調(diào)研聯(lián)考試卷附答案解析
- 河北省高職單招2024年數(shù)學(xué)真題仿真卷
- 2025年全球貿(mào)易合同樣式
- 2025年車載高壓空壓機組項目提案報告模范
- 2025年鐵礦石采選項目立項申請報告模范
- 2025年勞動力輸入安全保障協(xié)議
- 2025年上饒年終合同樣本
- 2025年中外著作權(quán)許可使用合同樣本
- 中央企業(yè)人工智能應(yīng)用場景案例白皮書(2024年版)-中央企業(yè)人工智能協(xié)同創(chuàng)新平臺
- 《會務(wù)的組織和管理》課件
- 《倒虹吸管安全評價導(dǎo)則》
- 2025年中國濕度傳感器行業(yè)深度分析、投資前景、趨勢預(yù)測報告(智研咨詢)
- 人民調(diào)解知識課件
- 《儒林外史》(第13-30回)-初中整本書閱讀系列之《儒林外史》
- 污水處理中的應(yīng)急預(yù)案與處置措施考核試卷
- 甘肅省蘭州市蘭煉一中2025屆數(shù)學(xué)高一上期末統(tǒng)考試題含解析
- 期末試卷(試題)-2024-2025學(xué)年三年級上冊數(shù)學(xué)冀教版
- “小學(xué)英語對話教學(xué)”研究課題方案
- 城市地下管網(wǎng)建設(shè)工程投標書(范文)
評論
0/150
提交評論